mirror of
https://github.com/Xiao-MoMi/Custom-Crops.git
synced 2025-12-22 16:39:36 +00:00
1.5.19-PRE1
This commit is contained in:
@@ -1,146 +0,0 @@
|
|||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
## ##
|
|
||||||
## 本配置文件为范例 ##
|
|
||||||
## 仅作为参考测试用 ##
|
|
||||||
## ##
|
|
||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
info:
|
|
||||||
namespace: customcrops
|
|
||||||
items:
|
|
||||||
cabbage_stage_1:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/stage_1
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
cabbage_stage_2:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/stage_2
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
cabbage_stage_3:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/stage_3
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
cabbage_stage_4:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/stage_4
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
cabbage_seeds:
|
|
||||||
display_name: "卷心菜种子"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/cabbage_seeds
|
|
||||||
cabbage:
|
|
||||||
display_name: "卷心菜"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: cabbage/cabbage
|
|
||||||
cabbage_silver_star:
|
|
||||||
display_name: "卷心菜"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: cabbage/cabbage_silver_star
|
|
||||||
cabbage_golden_star:
|
|
||||||
display_name: "卷心菜"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: cabbage/cabbage_golden_star
|
|
||||||
gigantic_cabbage:
|
|
||||||
display_name: "巨型卷心菜"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: cabbage/gigantic_cabbage
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_TRANSPARENT
|
|
||||||
loots:
|
|
||||||
blocks:
|
|
||||||
cabbage_stage_1:
|
|
||||||
type: customcrops:cabbage_stage_1
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:cabbage_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
cabbage_stage_2:
|
|
||||||
type: customcrops:cabbage_stage_2
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:cabbage_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
cabbage_stage_3:
|
|
||||||
type: customcrops:cabbage_stage_3
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:cabbage_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
# cabbage_stage_4:
|
|
||||||
# type: customcrops:cabbage_stage_4
|
|
||||||
# items:
|
|
||||||
# result_1:
|
|
||||||
# item: customcrops:cabbage
|
|
||||||
# min_amount: 1
|
|
||||||
# max_amount: 3
|
|
||||||
# chance: 100
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
info:
|
|
||||||
namespace: customcrops
|
|
||||||
categories:
|
|
||||||
customcrops:
|
|
||||||
enabled: true
|
|
||||||
icon: customcrops:tomato_seeds
|
|
||||||
name: '自定义农作物'
|
|
||||||
items:
|
|
||||||
- customcrops:pot
|
|
||||||
- customcrops:watered_pot
|
|
||||||
- customcrops:sprinkler_1_item
|
|
||||||
- customcrops:sprinkler_2_item
|
|
||||||
- customcrops:greenhouse_glass
|
|
||||||
- customcrops:soil_detector
|
|
||||||
- customcrops:watering_can_1
|
|
||||||
- customcrops:watering_can_2
|
|
||||||
- customcrops:watering_can_3
|
|
||||||
- customcrops:watering_can_4
|
|
||||||
- customcrops:speed_1
|
|
||||||
- customcrops:speed_2
|
|
||||||
- customcrops:speed_3
|
|
||||||
- customcrops:retaining_1
|
|
||||||
- customcrops:retaining_2
|
|
||||||
- customcrops:retaining_3
|
|
||||||
- customcrops:quality_1
|
|
||||||
- customcrops:quality_2
|
|
||||||
- customcrops:quality_3
|
|
||||||
- customcrops:tomato
|
|
||||||
- customcrops:tomato_silver_star
|
|
||||||
- customcrops:tomato_golden_star
|
|
||||||
- customcrops:tomato_seeds
|
|
||||||
- customcrops:tomato_stage_1
|
|
||||||
- customcrops:tomato_stage_2
|
|
||||||
- customcrops:tomato_stage_3
|
|
||||||
- customcrops:tomato_stage_4
|
|
||||||
- customcrops:gigantic_tomato
|
|
||||||
- customcrops:cabbage
|
|
||||||
- customcrops:cabbage_silver_star
|
|
||||||
- customcrops:cabbage_golden_star
|
|
||||||
- customcrops:cabbage_seeds
|
|
||||||
- customcrops:cabbage_stage_1
|
|
||||||
- customcrops:cabbage_stage_2
|
|
||||||
- customcrops:cabbage_stage_3
|
|
||||||
- customcrops:cabbage_stage_4
|
|
||||||
- customcrops:gigantic_cabbage
|
|
||||||
- customcrops:grape
|
|
||||||
- customcrops:grape_silver_star
|
|
||||||
- customcrops:grape_golden_star
|
|
||||||
- customcrops:grape_seeds
|
|
||||||
- customcrops:grape_stage_1
|
|
||||||
- customcrops:grape_stage_2
|
|
||||||
- customcrops:grape_stage_3
|
|
||||||
- customcrops:grape_stage_4
|
|
||||||
- customcrops:grape_stage_5
|
|
||||||
- customcrops:grape_stage_6
|
|
||||||
- customcrops:corn
|
|
||||||
- customcrops:corn_silver_star
|
|
||||||
- customcrops:corn_golden_star
|
|
||||||
- customcrops:corn_seeds
|
|
||||||
- customcrops:corn_stage_1
|
|
||||||
- customcrops:corn_stage_2
|
|
||||||
- customcrops:corn_stage_3
|
|
||||||
- customcrops:corn_stage_4
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
## ##
|
|
||||||
## 本配置文件为范例 ##
|
|
||||||
## 仅作为参考测试用 ##
|
|
||||||
## ##
|
|
||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
info:
|
|
||||||
namespace: customcrops
|
|
||||||
items:
|
|
||||||
corn_stage_1:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: corn/stage_1
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
corn_stage_2:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: corn/stage_2
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
corn_stage_3:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: corn/stage_3
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
corn_stage_4:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: corn/stage_4
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
corn_seeds:
|
|
||||||
display_name: "玉米种子"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: corn/corn_seeds
|
|
||||||
corn:
|
|
||||||
display_name: "玉米"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: corn/corn
|
|
||||||
corn_silver_star:
|
|
||||||
display_name: "玉米"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: corn/corn_silver_star
|
|
||||||
corn_golden_star:
|
|
||||||
display_name: "玉米"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: corn/corn_golden_star
|
|
||||||
loots:
|
|
||||||
blocks:
|
|
||||||
corn_stage_1:
|
|
||||||
type: customcrops:corn_stage_1
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:corn_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
corn_stage_2:
|
|
||||||
type: customcrops:corn_stage_2
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:corn_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
corn_stage_3:
|
|
||||||
type: customcrops:corn_stage_3
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:corn_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
# corn_stage_4:
|
|
||||||
# type: customcrops:corn_stage_4
|
|
||||||
# items:
|
|
||||||
# result_1:
|
|
||||||
# item: customcrops:corn
|
|
||||||
# min_amount: 1
|
|
||||||
# max_amount: 1
|
|
||||||
# chance: 100
|
|
||||||
# ignore_fortune: true
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
## ##
|
|
||||||
## 本配置文件为范例 ##
|
|
||||||
## 仅作为参考测试用 ##
|
|
||||||
## ##
|
|
||||||
#############################################
|
|
||||||
#############################################
|
|
||||||
info:
|
|
||||||
namespace: customcrops
|
|
||||||
items:
|
|
||||||
grape_stage_1:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_1
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_stage_2:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_2
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_stage_3:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_3
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_stage_4:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_4
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_stage_5:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_5
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_stage_6:
|
|
||||||
display_name: ""
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/stage_6
|
|
||||||
specific_properties:
|
|
||||||
block:
|
|
||||||
placed_model:
|
|
||||||
type: REAL_WIRE
|
|
||||||
cancel_drop: true
|
|
||||||
sound:
|
|
||||||
place:
|
|
||||||
name: block.azalea.place
|
|
||||||
break:
|
|
||||||
name: block.azalea.break
|
|
||||||
grape_seeds:
|
|
||||||
display_name: "葡萄种子"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: PAPER
|
|
||||||
model_path: grape/grape_seeds
|
|
||||||
grape:
|
|
||||||
display_name: "葡萄"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: grape/grape
|
|
||||||
grape_silver_star:
|
|
||||||
display_name: "葡萄"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: grape/grape_silver_star
|
|
||||||
grape_golden_star:
|
|
||||||
display_name: "葡萄"
|
|
||||||
resource:
|
|
||||||
generate: false
|
|
||||||
material: APPLE
|
|
||||||
model_path: grape/grape_golden_star
|
|
||||||
loots:
|
|
||||||
blocks:
|
|
||||||
grape_stage_1:
|
|
||||||
type: customcrops:grape_stage_1
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:grape_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
grape_stage_2:
|
|
||||||
type: customcrops:grape_stage_2
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:grape_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
grape_stage_3:
|
|
||||||
type: customcrops:grape_stage_3
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:grape_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
grape_stage_4:
|
|
||||||
type: customcrops:grape_stage_4
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:grape_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
grape_stage_5:
|
|
||||||
type: customcrops:grape_stage_5
|
|
||||||
items:
|
|
||||||
result_1:
|
|
||||||
item: customcrops:grape_seeds
|
|
||||||
min_amount: 1
|
|
||||||
max_amount: 1
|
|
||||||
chance: 100
|
|
||||||
ignore_fortune: true
|
|
||||||
# grape_stage_6:
|
|
||||||
# type: customcrops:grape_stage_6
|
|
||||||
# items:
|
|
||||||
# result_1:
|
|
||||||
# item: customcrops:grape
|
|
||||||
# min_amount: 1
|
|
||||||
# max_amount: 3
|
|
||||||
# chance: 100
|
|
||||||
80
README.md
80
README.md
@@ -1,80 +0,0 @@
|
|||||||

|
|
||||||
|
|
||||||
|
|
||||||
# Custom-Crops
|
|
||||||
StardewValley Like Farming System
|
|
||||||
|
|
||||||
### How to buy
|
|
||||||
|
|
||||||
https://afdian.net/@xiaomomi
|
|
||||||
|
|
||||||
https://polymart.org/resource/customcrops.2625
|
|
||||||
|
|
||||||
### How to compile
|
|
||||||
Just compile it with -gradle shadowjar. Some premium plugins are used as
|
|
||||||
local libraries. If you don't need those integrations just remove them!
|
|
||||||
Default ItemsAdder Config is also included in this project, which will
|
|
||||||
provide a template and help you understand how this plugin works.
|
|
||||||
|
|
||||||
### Game Mechanics
|
|
||||||
Crops will grow at a specified time which you will see in the config.\
|
|
||||||
1000 is default (7am) As we know, Minecraft has 24000 ticks / Day\
|
|
||||||
All crops will grow successively if their pot is watered.
|
|
||||||
|
|
||||||
### Season & Greenhouse
|
|
||||||
Season is an important part of StardewValley Farming System
|
|
||||||
which means crops only grow in a suitable season. Inproper
|
|
||||||
seasons will make crops into dead stage but you can use
|
|
||||||
greenhouse glass to allow them grow all year.\
|
|
||||||
Season change has two modes: Automatic and Command\
|
|
||||||
You might use command to change season to sync other plugin's season for example RealisticSeason.
|
|
||||||
|
|
||||||
### Fertilizer
|
|
||||||
There are three templates of fertiziliers: \
|
|
||||||
SpeedGrow: Crops have a small chance to grow two stages at a time\
|
|
||||||
RetainingSoil: Pot have a small chance to retain its water after crops grow\
|
|
||||||
QuailityCrops: When haveresting, players have a higher chance to get high quality crops.
|
|
||||||
|
|
||||||
### Sprinkler & WateringCan
|
|
||||||
Sprinkler is a semi-automatic way of watering pot. You can add water to sprinkler with
|
|
||||||
water bucket or watering can. Max storage and range can be customized.\
|
|
||||||
Watering can also has its max storage and range. 1x1 1x3 3x3 and even 9x99 is supported!
|
|
||||||
|
|
||||||
### OverWeight
|
|
||||||
If configurated, crops will still absorb water every day and have a very little chance to be OverWeight(gigantic) before it's dead.
|
|
||||||
|
|
||||||
### Quality
|
|
||||||
Crops have three qualities, if you don't want this feature just disable it in config.
|
|
||||||
Quality is determined by the fertizilier players use and their luck!
|
|
||||||
|
|
||||||
### Harvest Repeatedly
|
|
||||||
If configurated, crops can be harvested with hands repeatedly and return to a specified stage.
|
|
||||||
|
|
||||||
### Highly Optimizied
|
|
||||||
1.Crops only grow at the specified time and won't impact the performance in other times.\
|
|
||||||
2.Growing judge is async and only the last step ** replace blcoks ** is sync.\
|
|
||||||
3.Crops will not actually grow at the same time. It's laggy to replace so many blocks at the same time. They will grow in a random time(in seconds) which you can specified in the config after "grow-time"(7am default)\
|
|
||||||
4.Defaultly crops will only grow in loaded chunks. If you want a mechanic similar to OriginRealms just DISABLE SEASON, GIGANTIC(OverWeight) and REPEATED HARVESTING.\
|
|
||||||
In this way crops data will be removed from file after it comes to its max stage. In other words, plugin will only record the crops still on growing.\
|
|
||||||
NEVER SET "only-grow-in-loaded-chunks" FALSE IF YOU DON'T DISABLE THE THREE FEATURES MENTIONED ABOVE.
|
|
||||||
|
|
||||||
### Commands
|
|
||||||
/customcrops setseason [world] [season] # set a specified world's season\
|
|
||||||
/customcrops reload # reload the plugin\
|
|
||||||
/customcrops backup # back up the data\
|
|
||||||
/customcrops forcegrow [world] # force a specified world's crops to grow a stage\
|
|
||||||
/customcrops forcewater [world] # force a specified world's sprinklers to work\
|
|
||||||
/customcrops forcesave [file] # save the cache to file
|
|
||||||
|
|
||||||
### Placeholders
|
|
||||||
%customcrops_season% show the season in the world\
|
|
||||||
%customcrops_season_[world]%\
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
|
|
||||||
>>>>>>> 5b4051e47471e1fef498039557036ccff8060511
|
|
||||||
==== these papi below will be accurate only in "Auto" mode ====\
|
|
||||||
%customcrops_nextseason% show the days to the next season\
|
|
||||||
%customcrops_nextseason_[world]%\
|
|
||||||
%customcrops_current% show the days the current season has gone\
|
|
||||||
%customcrops_current_[world]%
|
|
||||||
@@ -5,7 +5,7 @@ plugins {
|
|||||||
|
|
||||||
|
|
||||||
group = 'net.momirealms'
|
group = 'net.momirealms'
|
||||||
version = '1.5.18'
|
version = '1.5.19'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ public class ConfigReader {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><white>" + SPRINKLERS.size()/2 + "<color:#FFEBCD> srpinklers loaded!");
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><white>" + SPRINKLERS.size()/2 + "<color:#FFEBCD> sprinklers loaded!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,10 +505,22 @@ public class ConfigReader {
|
|||||||
});
|
});
|
||||||
cropInstance.setRequirements(requirements);
|
cropInstance.setRequirements(requirements);
|
||||||
}
|
}
|
||||||
|
if (config.contains("crops." + key + ".grow-chance")){
|
||||||
|
cropInstance.setGrowChance(config.getDouble("crops." + key + ".grow-chance"));
|
||||||
|
}else {
|
||||||
|
cropInstance.setGrowChance(1);
|
||||||
|
}
|
||||||
if (Config.quality){
|
if (Config.quality){
|
||||||
cropInstance.setQuality_1(config.getString("crops." + key + ".quality.1"));
|
cropInstance.setQuality_1(config.getString("crops." + key + ".quality.1"));
|
||||||
cropInstance.setQuality_2(config.getString("crops." + key + ".quality.2"));
|
cropInstance.setQuality_2(config.getString("crops." + key + ".quality.2"));
|
||||||
cropInstance.setQuality_3(config.getString("crops." + key + ".quality.3"));
|
cropInstance.setQuality_3(config.getString("crops." + key + ".quality.3"));
|
||||||
|
if (config.contains("crops." + key + ".drop-ia-loots")){
|
||||||
|
cropInstance.setDropIALoot(config.getBoolean("crops." + key + ".drop-ia-loots"));
|
||||||
|
}else {
|
||||||
|
cropInstance.setDropIALoot(false);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
cropInstance.setDropIALoot(false);
|
||||||
}
|
}
|
||||||
CROPS.put(key, cropInstance);
|
CROPS.put(key, cropInstance);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -42,11 +42,18 @@ public final class CustomCrops extends JavaPlugin {
|
|||||||
|
|
||||||
public static JavaPlugin instance;
|
public static JavaPlugin instance;
|
||||||
public static BukkitAudiences adventure;
|
public static BukkitAudiences adventure;
|
||||||
|
|
||||||
private CropTimer cropTimer;
|
private CropTimer cropTimer;
|
||||||
private CropManager cropManager;
|
private CropManager cropManager;
|
||||||
private SprinklerManager sprinklerManager;
|
private SprinklerManager sprinklerManager;
|
||||||
private SeasonManager seasonManager;
|
private SeasonManager seasonManager;
|
||||||
private PotManager potManager;
|
private PotManager potManager;
|
||||||
|
private Placeholders placeholders;
|
||||||
|
|
||||||
|
public CropManager getCropManager() { return this.cropManager; }
|
||||||
|
public SprinklerManager getSprinklerManager() { return sprinklerManager; }
|
||||||
|
public SeasonManager getSeasonManager() { return seasonManager; }
|
||||||
|
public PotManager getPotManager() { return potManager; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
@@ -56,40 +63,83 @@ public final class CustomCrops extends JavaPlugin {
|
|||||||
|
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#FFEBCD>Running on " + Bukkit.getVersion());
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#FFEBCD>Running on " + Bukkit.getVersion());
|
||||||
|
|
||||||
//加载配置文件
|
|
||||||
ConfigReader.ReloadConfig();
|
ConfigReader.ReloadConfig();
|
||||||
|
|
||||||
//PAPI
|
|
||||||
if(Bukkit.getPluginManager().getPlugin("PlaceHolderAPI") != null){
|
if(Bukkit.getPluginManager().getPlugin("PlaceHolderAPI") != null){
|
||||||
new Placeholders().register();
|
placeholders = new Placeholders();
|
||||||
|
placeholders.register();
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><gold>PlaceHolderAPI <color:#FFEBCD>Hooked!");
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><gold>PlaceHolderAPI <color:#FFEBCD>Hooked!");
|
||||||
}
|
}
|
||||||
|
|
||||||
//指令注册
|
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(new Executor(this));
|
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(new Executor(this));
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(new Completer());
|
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(new Completer());
|
||||||
|
|
||||||
//注册事件
|
|
||||||
Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this);
|
Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this);
|
||||||
Bukkit.getPluginManager().registerEvents(new RightClick(), this);
|
Bukkit.getPluginManager().registerEvents(new RightClick(), this);
|
||||||
Bukkit.getPluginManager().registerEvents(new BreakBlock(), this);
|
Bukkit.getPluginManager().registerEvents(new BreakBlock(), this);
|
||||||
Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this);
|
Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this);
|
||||||
|
|
||||||
//开始计时器
|
|
||||||
this.cropTimer = new CropTimer(this);
|
|
||||||
|
|
||||||
//载入数据
|
|
||||||
if (ConfigReader.Season.enable){
|
if (ConfigReader.Season.enable){
|
||||||
this.seasonManager = new SeasonManager(this);
|
this.seasonManager = new SeasonManager();
|
||||||
this.seasonManager.loadData();
|
this.seasonManager.loadData();
|
||||||
}
|
}
|
||||||
this.cropManager = new CropManager(this);
|
this.cropManager = new CropManager();
|
||||||
this.cropManager.loadData();
|
this.cropManager.loadData();
|
||||||
this.sprinklerManager = new SprinklerManager(this);
|
this.sprinklerManager = new SprinklerManager();
|
||||||
this.sprinklerManager.loadData();
|
this.sprinklerManager.loadData();
|
||||||
this.potManager = new PotManager(this);
|
this.potManager = new PotManager();
|
||||||
this.potManager.loadData();
|
this.potManager.loadData();
|
||||||
|
this.cropTimer = new CropTimer(this);
|
||||||
|
|
||||||
|
checkIAConfig();
|
||||||
|
|
||||||
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#F5DEB3>Plugin Enabled!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
|
||||||
|
HoloUtil.cache.keySet().forEach(location -> HoloUtil.cache.get(location).remove());
|
||||||
|
|
||||||
|
if (this.cropManager != null){
|
||||||
|
this.cropManager.cleanData();
|
||||||
|
this.cropManager.saveData();
|
||||||
|
this.cropManager = null;
|
||||||
|
}
|
||||||
|
if (this.potManager != null){
|
||||||
|
this.potManager.saveData();
|
||||||
|
this.potManager = null;
|
||||||
|
}
|
||||||
|
if (this.sprinklerManager != null){
|
||||||
|
this.sprinklerManager.cleanData();
|
||||||
|
this.sprinklerManager.saveData();
|
||||||
|
this.sprinklerManager = null;
|
||||||
|
}
|
||||||
|
if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange && this.seasonManager != null){
|
||||||
|
this.seasonManager.saveData();
|
||||||
|
this.seasonManager = null;
|
||||||
|
}
|
||||||
|
if (this.placeholders != null){
|
||||||
|
placeholders.unregister();
|
||||||
|
placeholders = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogger().info("Backing Up...");
|
||||||
|
BackUp.backUpData();
|
||||||
|
getLogger().info("Done.");
|
||||||
|
|
||||||
|
if (cropTimer != null) {
|
||||||
|
this.cropTimer.stopTimer(cropTimer.getTaskID());
|
||||||
|
}
|
||||||
|
if (adventure != null) {
|
||||||
|
adventure.close();
|
||||||
|
}
|
||||||
|
if (instance != null) {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIAConfig(){
|
||||||
FileConfiguration fileConfiguration = Bukkit.getPluginManager().getPlugin("ItemsAdder").getConfig();
|
FileConfiguration fileConfiguration = Bukkit.getPluginManager().getPlugin("ItemsAdder").getConfig();
|
||||||
if (fileConfiguration.getBoolean("blocks.disable-REAL_WIRE")){
|
if (fileConfiguration.getBoolean("blocks.disable-REAL_WIRE")){
|
||||||
fileConfiguration.set("blocks.disable-REAL_WIRE", false);
|
fileConfiguration.set("blocks.disable-REAL_WIRE", false);
|
||||||
@@ -100,46 +150,6 @@ public final class CustomCrops extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><red>Detected that you might have not set \"disable-REAL_WIRE\" false in ItemsAdder's config!");
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><red>Detected that you might have not set \"disable-REAL_WIRE\" false in ItemsAdder's config!");
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><red>You need a restart to apply that config :)");
|
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><red>You need a restart to apply that config :)");
|
||||||
}else {
|
|
||||||
AdventureManager.consoleMessage("<gradient:#ff206c:#fdee55>[CustomCrops] </gradient><color:#F5DEB3>Plugin Enabled!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisable() {
|
|
||||||
|
|
||||||
//保存数据
|
|
||||||
this.cropManager.cleanData();
|
|
||||||
this.cropManager.saveData();
|
|
||||||
this.sprinklerManager.cleanData();
|
|
||||||
this.sprinklerManager.saveData();
|
|
||||||
this.potManager.saveData();
|
|
||||||
if (ConfigReader.Season.enable && !ConfigReader.Season.seasonChange){
|
|
||||||
this.seasonManager.saveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
//备份数据
|
|
||||||
getLogger().info("Back Up...");
|
|
||||||
BackUp.backUpData();
|
|
||||||
getLogger().info("Done.");
|
|
||||||
|
|
||||||
//清除悬浮展示实体
|
|
||||||
HoloUtil.cache.keySet().forEach(location -> {
|
|
||||||
HoloUtil.cache.get(location).remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
//关闭计时器
|
|
||||||
if (cropTimer != null) {
|
|
||||||
this.cropTimer.stopTimer(cropTimer.getTaskID());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adventure != null) {
|
|
||||||
adventure.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CropManager getCropManager() { return this.cropManager; }
|
|
||||||
public SprinklerManager getSprinklerManager() { return sprinklerManager; }
|
|
||||||
public SeasonManager getSeasonManager() { return seasonManager; }
|
|
||||||
public PotManager getPotManager() { return potManager; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ public class Executor implements CommandExecutor {
|
|||||||
@Override
|
@Override
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
//权限不足
|
|
||||||
if (!(sender.hasPermission("customcrops.admin") || sender.isOp())){
|
if (!(sender.hasPermission("customcrops.admin") || sender.isOp())){
|
||||||
AdventureManager.playerMessage((Player) sender, ConfigReader.Message.prefix + ConfigReader.Message.noPerm);
|
AdventureManager.playerMessage((Player) sender, ConfigReader.Message.prefix + ConfigReader.Message.noPerm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//参数不足
|
|
||||||
if (args.length < 1) {
|
if (args.length < 1) {
|
||||||
lackArgs(sender);
|
lackArgs(sender);
|
||||||
return true;
|
return true;
|
||||||
@@ -182,6 +182,10 @@ public class Executor implements CommandExecutor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缺少参数的提示语
|
||||||
|
* @param sender 发送者
|
||||||
|
*/
|
||||||
private void lackArgs(CommandSender sender){
|
private void lackArgs(CommandSender sender){
|
||||||
if (sender instanceof Player){
|
if (sender instanceof Player){
|
||||||
AdventureManager.playerMessage((Player) sender,ConfigReader.Message.prefix + ConfigReader.Message.lackArgs);
|
AdventureManager.playerMessage((Player) sender,ConfigReader.Message.prefix + ConfigReader.Message.lackArgs);
|
||||||
@@ -190,6 +194,10 @@ public class Executor implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制保存的提示语
|
||||||
|
* @param sender 发送者
|
||||||
|
*/
|
||||||
private void forceSave(CommandSender sender){
|
private void forceSave(CommandSender sender){
|
||||||
if (sender instanceof Player player){
|
if (sender instanceof Player player){
|
||||||
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceSave);
|
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceSave);
|
||||||
|
|||||||
@@ -45,16 +45,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class CropManager {
|
public class CropManager {
|
||||||
|
|
||||||
private YamlConfiguration data;
|
private YamlConfiguration data;
|
||||||
private final CustomCrops plugin;
|
|
||||||
public static ConcurrentHashMap<Location, String> Cache = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Location, String> Cache = new ConcurrentHashMap<>();
|
||||||
private BukkitScheduler bukkitScheduler;
|
private final BukkitScheduler bukkitScheduler;
|
||||||
|
|
||||||
public CropManager(CustomCrops plugin){
|
public CropManager(){
|
||||||
this.plugin = plugin;
|
|
||||||
this.bukkitScheduler = Bukkit.getScheduler();
|
this.bukkitScheduler = Bukkit.getScheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
//载入数据
|
/**
|
||||||
|
* 载入数据
|
||||||
|
*/
|
||||||
public void loadData() {
|
public void loadData() {
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml");
|
||||||
if(!file.exists()){
|
if(!file.exists()){
|
||||||
@@ -69,7 +69,9 @@ public class CropManager {
|
|||||||
this.data = YamlConfiguration.loadConfiguration(file);
|
this.data = YamlConfiguration.loadConfiguration(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
//保存数据
|
/**
|
||||||
|
* 保存数据
|
||||||
|
*/
|
||||||
public void saveData() {
|
public void saveData() {
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "crop.yml");
|
||||||
try{
|
try{
|
||||||
@@ -80,7 +82,9 @@ public class CropManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//将缓存内新数据更新到data内
|
/**
|
||||||
|
* 将hashmap中的数据保存到data中
|
||||||
|
*/
|
||||||
public void updateData(){
|
public void updateData(){
|
||||||
Cache.forEach((location, String) -> {
|
Cache.forEach((location, String) -> {
|
||||||
int x = location.getBlockX();
|
int x = location.getBlockX();
|
||||||
@@ -90,7 +94,9 @@ public class CropManager {
|
|||||||
Cache.clear();
|
Cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//隐藏指令,清除无用数据
|
/**
|
||||||
|
* 清除无用数据
|
||||||
|
*/
|
||||||
public void cleanData(){
|
public void cleanData(){
|
||||||
data.getKeys(false).forEach(world -> {
|
data.getKeys(false).forEach(world -> {
|
||||||
data.getConfigurationSection(world).getKeys(false).forEach(chunk ->{
|
data.getConfigurationSection(world).getKeys(false).forEach(chunk ->{
|
||||||
@@ -101,7 +107,10 @@ public class CropManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//农作物生长
|
/**
|
||||||
|
* 农作物生长
|
||||||
|
* @param worldName 进行生长判定的世界名
|
||||||
|
*/
|
||||||
public void cropGrow(String worldName){
|
public void cropGrow(String worldName){
|
||||||
|
|
||||||
Long time1 = System.currentTimeMillis();
|
Long time1 = System.currentTimeMillis();
|
||||||
@@ -155,7 +164,7 @@ public class CropManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||||
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) {
|
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) {
|
||||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
|
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
|
||||||
if (fertilizer != null){
|
if (fertilizer != null){
|
||||||
int times = fertilizer.getTimes();
|
int times = fertilizer.getTimes();
|
||||||
@@ -229,7 +238,10 @@ public class CropManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//农作物生长
|
/**
|
||||||
|
* 全部世界农作物生长
|
||||||
|
* 对于使用动态加载世界的服务器有效
|
||||||
|
*/
|
||||||
public void cropGrowAll(){
|
public void cropGrowAll(){
|
||||||
Long time1 = System.currentTimeMillis();
|
Long time1 = System.currentTimeMillis();
|
||||||
updateData();
|
updateData();
|
||||||
@@ -271,7 +283,6 @@ public class CropManager {
|
|||||||
CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
|
CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
|
||||||
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
|
||||||
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
|
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
|
||||||
//如果启用季节限制且农作物有季节需求
|
|
||||||
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
|
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
|
||||||
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
|
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
|
||||||
data.set(stringBuilder.toString(), null);
|
data.set(stringBuilder.toString(), null);
|
||||||
@@ -283,7 +294,7 @@ public class CropManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||||
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) {
|
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) {
|
||||||
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
|
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
|
||||||
if (fertilizer != null){
|
if (fertilizer != null){
|
||||||
int times = fertilizer.getTimes();
|
int times = fertilizer.getTimes();
|
||||||
@@ -358,6 +369,12 @@ public class CropManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判定季节
|
||||||
|
* @param worldName 世界名
|
||||||
|
* @param seasons 农作物能生长的季节
|
||||||
|
* @param seedLocation 农作物的位置
|
||||||
|
*/
|
||||||
private boolean isWrongSeason(Location seedLocation, List<String> seasons, String worldName){
|
private boolean isWrongSeason(Location seedLocation, List<String> seasons, String worldName){
|
||||||
if(ConfigReader.Season.greenhouse){
|
if(ConfigReader.Season.greenhouse){
|
||||||
for(int i = 1; i <= ConfigReader.Season.range; i++){
|
for(int i = 1; i <= ConfigReader.Season.range; i++){
|
||||||
@@ -385,19 +402,36 @@ public class CropManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生长一个阶段(消耗水)
|
||||||
|
* @param potLocation 种植盆位置
|
||||||
|
* @param seedLocation 农作物位置
|
||||||
|
* @param namespacedID 农作物下一阶段的ID
|
||||||
|
* @param nextStage 农作物下一阶段的阶段数
|
||||||
|
* @param random 随机生长时间
|
||||||
|
*/
|
||||||
private void addStage(Location potLocation, Location seedLocation, String namespacedID, int nextStage, int random){
|
private void addStage(Location potLocation, Location seedLocation, String namespacedID, int nextStage, int random){
|
||||||
|
String stage = StringUtils.chop(namespacedID) + nextStage;
|
||||||
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
|
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
|
||||||
CustomBlock.remove(potLocation);
|
CustomBlock.remove(potLocation);
|
||||||
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
|
||||||
CustomBlock.remove(seedLocation);
|
CustomBlock.remove(seedLocation);
|
||||||
CustomBlock.place(StringUtils.chop(namespacedID) + nextStage, seedLocation);
|
CustomBlock.place(stage, seedLocation);
|
||||||
}, random);
|
}, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生长一个阶段(不消耗水)
|
||||||
|
* @param seedLocation 农作物位置
|
||||||
|
* @param namespacedID 农作物下一阶段的ID
|
||||||
|
* @param nextStage 农作物下一阶段的阶段数
|
||||||
|
* @param random 随机生长时间
|
||||||
|
*/
|
||||||
private void addStage(Location seedLocation, String namespacedID, int nextStage, int random){
|
private void addStage(Location seedLocation, String namespacedID, int nextStage, int random){
|
||||||
|
String stage = StringUtils.chop(namespacedID) + nextStage;
|
||||||
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
|
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
|
||||||
CustomBlock.remove(seedLocation);
|
CustomBlock.remove(seedLocation);
|
||||||
CustomBlock.place(StringUtils.chop(namespacedID) + nextStage, seedLocation);
|
CustomBlock.place(stage, seedLocation);
|
||||||
}, random);
|
}, random);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
public class PotManager {
|
public class PotManager {
|
||||||
|
|
||||||
private CustomCrops plugin;
|
|
||||||
public static ConcurrentHashMap<SimpleLocation, Fertilizer> Cache = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<SimpleLocation, Fertilizer> Cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public PotManager(CustomCrops plugin){
|
/**
|
||||||
this.plugin = plugin;
|
* 载入数据
|
||||||
}
|
*/
|
||||||
|
|
||||||
public void loadData(){
|
public void loadData(){
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml");
|
||||||
if(!file.exists()){
|
if(!file.exists()){
|
||||||
@@ -65,13 +63,10 @@ public class PotManager {
|
|||||||
if (fertilizer == null) return;
|
if (fertilizer == null) return;
|
||||||
if (fertilizer instanceof SpeedGrow speedGrow){
|
if (fertilizer instanceof SpeedGrow speedGrow){
|
||||||
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new SpeedGrow(name, (int) map.get("times"), speedGrow.getChance(), speedGrow.isBefore()));
|
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new SpeedGrow(name, (int) map.get("times"), speedGrow.getChance(), speedGrow.isBefore()));
|
||||||
//Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new SpeedGrow(name, (int) map.get("times"), speedGrow.getChance(), speedGrow.isBefore()));
|
|
||||||
}else if (fertilizer instanceof QualityCrop qualityCrop){
|
}else if (fertilizer instanceof QualityCrop qualityCrop){
|
||||||
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new QualityCrop(name, (int) map.get("times"), qualityCrop.getChance(), qualityCrop.isBefore()));
|
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new QualityCrop(name, (int) map.get("times"), qualityCrop.getChance(), qualityCrop.isBefore()));
|
||||||
//Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new QualityCrop(name, (int) map.get("times"), qualityCrop.getChance(), qualityCrop.isBefore()));
|
|
||||||
}else if (fertilizer instanceof RetainingSoil retainingSoil){
|
}else if (fertilizer instanceof RetainingSoil retainingSoil){
|
||||||
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new RetainingSoil(name, (int) map.get("times"), retainingSoil.getChance(), retainingSoil.isBefore()));
|
Cache.put(new SimpleLocation(worldName, Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])), new RetainingSoil(name, (int) map.get("times"), retainingSoil.getChance(), retainingSoil.isBefore()));
|
||||||
//Cache.put(new Location(Bukkit.getWorld(worldName), Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2])), new RetainingSoil(name, (int) map.get("times"), retainingSoil.getChance(), retainingSoil.isBefore()));
|
|
||||||
}else {
|
}else {
|
||||||
AdventureManager.consoleMessage("<red>[CustomCrops] 未知肥料类型错误!</red>");
|
AdventureManager.consoleMessage("<red>[CustomCrops] 未知肥料类型错误!</red>");
|
||||||
}
|
}
|
||||||
@@ -80,6 +75,9 @@ public class PotManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存数据
|
||||||
|
*/
|
||||||
public void saveData(){
|
public void saveData(){
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "pot.yml");
|
||||||
YamlConfiguration data = new YamlConfiguration();
|
YamlConfiguration data = new YamlConfiguration();
|
||||||
|
|||||||
@@ -30,10 +30,14 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public record SeasonManager(CustomCrops plugin) {
|
public class SeasonManager{
|
||||||
|
|
||||||
public static HashMap<String, String> SEASON = new HashMap<>();
|
public static HashMap<String, String> SEASON = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取文件中的季节
|
||||||
|
* @param file 季节数据文件
|
||||||
|
*/
|
||||||
private YamlConfiguration readData(File file) {
|
private YamlConfiguration readData(File file) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
try {
|
try {
|
||||||
@@ -47,6 +51,9 @@ public record SeasonManager(CustomCrops plugin) {
|
|||||||
return YamlConfiguration.loadConfiguration(file);
|
return YamlConfiguration.loadConfiguration(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 载入数据
|
||||||
|
*/
|
||||||
public void loadData() {
|
public void loadData() {
|
||||||
SEASON.clear();
|
SEASON.clear();
|
||||||
YamlConfiguration data = readData(new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml"));
|
YamlConfiguration data = readData(new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml"));
|
||||||
@@ -68,8 +75,11 @@ public record SeasonManager(CustomCrops plugin) {
|
|||||||
ConfigReader.Config.worlds.forEach(this::getSeason);
|
ConfigReader.Config.worlds.forEach(this::getSeason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算某个世界的季节
|
||||||
|
* @param world 世界
|
||||||
|
*/
|
||||||
public void getSeason(World world) {
|
public void getSeason(World world) {
|
||||||
|
|
||||||
int season = (int) ((world.getFullTime() / 24000L) % (ConfigReader.Season.duration * 4)) / ConfigReader.Season.duration;
|
int season = (int) ((world.getFullTime() / 24000L) % (ConfigReader.Season.duration * 4)) / ConfigReader.Season.duration;
|
||||||
switch (season) {
|
switch (season) {
|
||||||
case 0 -> SEASON.put(world.getName(), "spring");
|
case 0 -> SEASON.put(world.getName(), "spring");
|
||||||
@@ -80,6 +90,9 @@ public record SeasonManager(CustomCrops plugin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存数据
|
||||||
|
*/
|
||||||
public void saveData() {
|
public void saveData() {
|
||||||
SEASON.forEach((key, value) -> {
|
SEASON.forEach((key, value) -> {
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "season.yml");
|
||||||
@@ -94,6 +107,11 @@ public record SeasonManager(CustomCrops plugin) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置季节
|
||||||
|
* @param worldName 世界名
|
||||||
|
* @param season 季节
|
||||||
|
*/
|
||||||
public boolean setSeason(String worldName, String season){
|
public boolean setSeason(String worldName, String season){
|
||||||
if (!ConfigReader.Config.worldNames.contains(worldName)){
|
if (!ConfigReader.Config.worldNames.contains(worldName)){
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -39,13 +39,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class SprinklerManager {
|
public class SprinklerManager {
|
||||||
|
|
||||||
public YamlConfiguration data;
|
public YamlConfiguration data;
|
||||||
private final CustomCrops plugin;
|
|
||||||
public static ConcurrentHashMap<Location, Sprinkler> Cache = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Location, Sprinkler> Cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public SprinklerManager(CustomCrops plugin){
|
/**
|
||||||
this.plugin = plugin;
|
* 载入数据
|
||||||
}
|
*/
|
||||||
|
|
||||||
public void loadData() {
|
public void loadData() {
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml");
|
||||||
if(!file.exists()){
|
if(!file.exists()){
|
||||||
@@ -60,6 +58,9 @@ public class SprinklerManager {
|
|||||||
this.data = YamlConfiguration.loadConfiguration(file);
|
this.data = YamlConfiguration.loadConfiguration(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存数据
|
||||||
|
*/
|
||||||
public void saveData(){
|
public void saveData(){
|
||||||
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml");
|
File file = new File(CustomCrops.instance.getDataFolder(), "data" + File.separator + "sprinkler.yml");
|
||||||
try{
|
try{
|
||||||
@@ -70,6 +71,9 @@ public class SprinklerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理无用数据
|
||||||
|
*/
|
||||||
public void cleanData(){
|
public void cleanData(){
|
||||||
data.getKeys(false).forEach(world -> {
|
data.getKeys(false).forEach(world -> {
|
||||||
data.getConfigurationSection(world).getKeys(false).forEach(chunk ->{
|
data.getConfigurationSection(world).getKeys(false).forEach(chunk ->{
|
||||||
@@ -80,6 +84,9 @@ public class SprinklerManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将hashmap中的数据保存到data中
|
||||||
|
*/
|
||||||
public void updateData(){
|
public void updateData(){
|
||||||
Cache.forEach((location, sprinklerData) -> {
|
Cache.forEach((location, sprinklerData) -> {
|
||||||
String world = location.getWorld().getName();
|
String world = location.getWorld().getName();
|
||||||
@@ -92,6 +99,10 @@ public class SprinklerManager {
|
|||||||
Cache.clear();
|
Cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定世界的洒水器工作
|
||||||
|
* @param worldName 世界名
|
||||||
|
*/
|
||||||
public void sprinklerWork(String worldName){
|
public void sprinklerWork(String worldName){
|
||||||
Long time1 = System.currentTimeMillis();
|
Long time1 = System.currentTimeMillis();
|
||||||
updateData();
|
updateData();
|
||||||
@@ -146,6 +157,9 @@ public class SprinklerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有世界的洒水器工作
|
||||||
|
*/
|
||||||
public void sprinklerWorkAll(){
|
public void sprinklerWorkAll(){
|
||||||
Long time1 = System.currentTimeMillis();
|
Long time1 = System.currentTimeMillis();
|
||||||
updateData();
|
updateData();
|
||||||
@@ -202,6 +216,10 @@ public class SprinklerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转干为湿
|
||||||
|
* @param potLoc 种植盆的位置
|
||||||
|
*/
|
||||||
private void waterPot(Location potLoc) {
|
private void waterPot(Location potLoc) {
|
||||||
CustomBlock cb = CustomBlock.byAlreadyPlaced(potLoc.getBlock());
|
CustomBlock cb = CustomBlock.byAlreadyPlaced(potLoc.getBlock());
|
||||||
if(cb != null){
|
if(cb != null){
|
||||||
|
|||||||
@@ -33,43 +33,18 @@ public class QualityCrop implements Fertilizer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public String getKey() {return this.key;}
|
||||||
return this.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTimes() {
|
public int getTimes() {return this.times;}
|
||||||
return this.times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(int times) {
|
public void setTimes(int times) {this.times = times;}
|
||||||
this.times = times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBefore() {
|
public boolean isBefore() {return this.before;}
|
||||||
return this.before;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {return this.name;}
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {this.name = name;}
|
||||||
this.name = name;
|
public void setChance(int[] chance) {this.chance = chance;}
|
||||||
}
|
public void setKey(String key) {this.key = key;}
|
||||||
|
public int[] getChance() {return chance;}
|
||||||
public void setChance(int[] chance) {
|
|
||||||
this.chance = chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getChance() {
|
|
||||||
return chance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class RetainingSoil implements Fertilizer{
|
|||||||
private double chance;
|
private double chance;
|
||||||
private String key;
|
private String key;
|
||||||
private int times;
|
private int times;
|
||||||
private boolean before;
|
private final boolean before;
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public RetainingSoil(String key, int times, double chance, boolean before){
|
public RetainingSoil(String key, int times, double chance, boolean before){
|
||||||
@@ -33,43 +33,18 @@ public class RetainingSoil implements Fertilizer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public String getKey() {return this.key;}
|
||||||
return this.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTimes() {
|
public int getTimes() {return this.times;}
|
||||||
return this.times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(int times) {
|
public void setTimes(int times) {this.times = times;}
|
||||||
this.times = times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBefore() {
|
public boolean isBefore() {return this.before;}
|
||||||
return this.before;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {return this.name;}
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {this.name = name;}
|
||||||
this.name = name;
|
public void setChance(double chance) {this.chance = chance;}
|
||||||
}
|
public void setKey(String key) {this.key = key;}
|
||||||
|
public double getChance() {return chance;}
|
||||||
public void setChance(double chance) {
|
|
||||||
this.chance = chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getChance() {
|
|
||||||
return chance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,43 +33,18 @@ public class SpeedGrow implements Fertilizer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getKey() {
|
public String getKey() {return this.key;}
|
||||||
return this.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTimes() {
|
public int getTimes() {return this.times;}
|
||||||
return this.times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTimes(int times) {
|
public void setTimes(int times) {this.times = times;}
|
||||||
this.times = times;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBefore() {
|
public boolean isBefore() {return this.before;}
|
||||||
return this.before;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {return this.name;}
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {this.name = name;}
|
||||||
this.name = name;
|
public double getChance() {return chance;}
|
||||||
}
|
public void setChance(double chance) {this.chance = chance;}
|
||||||
|
public void setKey(String key) {this.key = key;}
|
||||||
public double getChance() {
|
|
||||||
return chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChance(double chance) {
|
|
||||||
this.chance = chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.common.base.Suppliers;
|
|
||||||
|
|
||||||
import net.momirealms.customcrops.CustomCrops;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
|
|
||||||
* into the classloader.
|
|
||||||
*/
|
|
||||||
@NonnullByDefault
|
|
||||||
public final class LibraryLoader {
|
|
||||||
|
|
||||||
@SuppressWarnings("Guava")
|
|
||||||
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomCrops.instance.getClass().getClassLoader()));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves all {@link MavenLibrary} annotations on the given object.
|
|
||||||
*
|
|
||||||
* @param object the object to load libraries for.
|
|
||||||
*/
|
|
||||||
public static void loadAll(Object object) {
|
|
||||||
loadAll(object.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves all {@link MavenLibrary} annotations on the given class.
|
|
||||||
*
|
|
||||||
* @param clazz the class to load libraries for.
|
|
||||||
*/
|
|
||||||
public static void loadAll(Class<?> clazz) {
|
|
||||||
MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
|
|
||||||
if (libs == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MavenLibrary lib : libs) {
|
|
||||||
load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void load(String groupId, String artifactId, String version, String repoUrl) {
|
|
||||||
load(new Dependency(groupId, artifactId, version, repoUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void load(Dependency d) {
|
|
||||||
//Log.info(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl()));
|
|
||||||
String name = d.getArtifactId() + "-" + d.getVersion();
|
|
||||||
|
|
||||||
File saveLocation = new File(getLibFolder(d), name + ".jar");
|
|
||||||
if (!saveLocation.exists()) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Log.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
|
|
||||||
URL url = d.getUrl();
|
|
||||||
|
|
||||||
try (InputStream is = url.openStream()) {
|
|
||||||
Files.copy(is, saveLocation.toPath());
|
|
||||||
Log.info("Dependency '" + name + "' successfully downloaded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!saveLocation.exists()) {
|
|
||||||
throw new RuntimeException("Unable to download dependency: " + d.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File getLibFolder(Dependency dependency) {
|
|
||||||
File pluginDataFolder = CustomCrops.instance.getDataFolder();
|
|
||||||
File serverDir = pluginDataFolder.getParentFile().getParentFile();
|
|
||||||
|
|
||||||
File helperDir = new File(serverDir, "libraries");
|
|
||||||
String[] split = StringUtils.split(dependency.getGroupId(), ".");
|
|
||||||
File jarDir = new File(helperDir, split[0] + File.separator + split[1] + File.separator + dependency.artifactId + File.separator + dependency.version );
|
|
||||||
jarDir.mkdirs();
|
|
||||||
return jarDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonnullByDefault
|
|
||||||
public static final class Dependency {
|
|
||||||
private final String groupId;
|
|
||||||
private final String artifactId;
|
|
||||||
private final String version;
|
|
||||||
private final String repoUrl;
|
|
||||||
|
|
||||||
public Dependency(String groupId, String artifactId, String version, String repoUrl) {
|
|
||||||
this.groupId = Objects.requireNonNull(groupId, "groupId");
|
|
||||||
this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
|
|
||||||
this.version = Objects.requireNonNull(version, "version");
|
|
||||||
this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGroupId() {
|
|
||||||
return this.groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getArtifactId() {
|
|
||||||
return this.artifactId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVersion() {
|
|
||||||
return this.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepoUrl() {
|
|
||||||
return this.repoUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public URL getUrl() throws MalformedURLException {
|
|
||||||
String repo = this.repoUrl;
|
|
||||||
if (!repo.endsWith("/")) {
|
|
||||||
repo += "/";
|
|
||||||
}
|
|
||||||
repo += "%s/%s/%s/%s-%s.jar";
|
|
||||||
|
|
||||||
String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
|
|
||||||
return new URL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o == this) return true;
|
|
||||||
if (!(o instanceof Dependency)) return false;
|
|
||||||
final Dependency other = (Dependency) o;
|
|
||||||
return this.getGroupId().equals(other.getGroupId()) &&
|
|
||||||
this.getArtifactId().equals(other.getArtifactId()) &&
|
|
||||||
this.getVersion().equals(other.getVersion()) &&
|
|
||||||
this.getRepoUrl().equals(other.getRepoUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int PRIME = 59;
|
|
||||||
int result = 1;
|
|
||||||
result = result * PRIME + this.getGroupId().hashCode();
|
|
||||||
result = result * PRIME + this.getArtifactId().hashCode();
|
|
||||||
result = result * PRIME + this.getVersion().hashCode();
|
|
||||||
result = result * PRIME + this.getRepoUrl().hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "LibraryLoader.Dependency(" +
|
|
||||||
"groupId=" + this.getGroupId() + ", " +
|
|
||||||
"artifactId=" + this.getArtifactId() + ", " +
|
|
||||||
"version=" + this.getVersion() + ", " +
|
|
||||||
"repoUrl=" + this.getRepoUrl() + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import net.momirealms.customcrops.CustomCrops;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility for quickly accessing a logger instance without using {@link Bukkit#getLogger()}
|
|
||||||
*/
|
|
||||||
public final class Log {
|
|
||||||
|
|
||||||
public static void info(@Nonnull String s) {
|
|
||||||
CustomCrops.instance.getLogger().info(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void warn(@Nonnull String s) {
|
|
||||||
CustomCrops.instance.getLogger().warning(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void severe(@Nonnull String s) {
|
|
||||||
CustomCrops.instance.getLogger().severe(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void warn(@Nonnull String s, Throwable t) {
|
|
||||||
CustomCrops.instance.getLogger().log(Level.WARNING, s, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void severe(@Nonnull String s, Throwable t) {
|
|
||||||
CustomCrops.instance.getLogger().log(Level.SEVERE, s, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Log() {
|
|
||||||
throw new UnsupportedOperationException("This class cannot be instantiated");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation to indicate the required libraries for a class.
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface MavenLibraries {
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
MavenLibrary[] value() default {};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Repeatable;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation to indicate a required library for a class.
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Repeatable(MavenLibraries.class)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface MavenLibrary {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The group id of the library
|
|
||||||
*
|
|
||||||
* @return the group id of the library
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
String groupId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The artifact id of the library
|
|
||||||
*
|
|
||||||
* @return the artifact id of the library
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
String artifactId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version of the library
|
|
||||||
*
|
|
||||||
* @return the version of the library
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
String version();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The repo where the library can be obtained from
|
|
||||||
*
|
|
||||||
* @return the repo where the library can be obtained from
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.meta.TypeQualifierDefault;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Documented
|
|
||||||
@TypeQualifierDefault({
|
|
||||||
ElementType.FIELD,
|
|
||||||
ElementType.METHOD,
|
|
||||||
ElementType.PARAMETER
|
|
||||||
})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface NonnullByDefault {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a maven repository.
|
|
||||||
*/
|
|
||||||
@Documented
|
|
||||||
@Target(ElementType.LOCAL_VARIABLE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface Repository {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the base url of the repository.
|
|
||||||
*
|
|
||||||
* @return the base url of the repository
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
String url();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of helper, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* Copyright (c) contributors
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.helper;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to {@link URLClassLoader}#addURL.
|
|
||||||
*/
|
|
||||||
public abstract class URLClassLoaderAccess {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@link URLClassLoaderAccess} for the given class loader.
|
|
||||||
*
|
|
||||||
* @param classLoader the class loader
|
|
||||||
* @return the access object
|
|
||||||
*/
|
|
||||||
static URLClassLoaderAccess create(URLClassLoader classLoader) {
|
|
||||||
if (Unsafe.isSupported()) {
|
|
||||||
return new Unsafe(classLoader);
|
|
||||||
} else {
|
|
||||||
return Noop.INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final URLClassLoader classLoader;
|
|
||||||
|
|
||||||
protected URLClassLoaderAccess(URLClassLoader classLoader) {
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the given URL to the class loader.
|
|
||||||
*
|
|
||||||
* @param url the URL to add
|
|
||||||
*/
|
|
||||||
public abstract void addURL(@Nonnull URL url);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accesses using sun.misc.Unsafe, supported on Java 9+.
|
|
||||||
*
|
|
||||||
* @author Vaishnav Anil (https://github.com/slimjar/slimjar)
|
|
||||||
*/
|
|
||||||
private static class Unsafe extends URLClassLoaderAccess {
|
|
||||||
private static final sun.misc.Unsafe UNSAFE;
|
|
||||||
|
|
||||||
static {
|
|
||||||
sun.misc.Unsafe unsafe;
|
|
||||||
try {
|
|
||||||
Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
|
|
||||||
unsafeField.setAccessible(true);
|
|
||||||
unsafe = (sun.misc.Unsafe) unsafeField.get(null);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
unsafe = null;
|
|
||||||
}
|
|
||||||
UNSAFE = unsafe;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isSupported() {
|
|
||||||
return UNSAFE != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Collection<URL> unopenedURLs;
|
|
||||||
private final Collection<URL> pathURLs;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Unsafe(URLClassLoader classLoader) {
|
|
||||||
super(classLoader);
|
|
||||||
|
|
||||||
Collection<URL> unopenedURLs;
|
|
||||||
Collection<URL> pathURLs;
|
|
||||||
try {
|
|
||||||
Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
|
|
||||||
unopenedURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "unopenedUrls");
|
|
||||||
pathURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "path");
|
|
||||||
} catch (Throwable e) {
|
|
||||||
unopenedURLs = null;
|
|
||||||
pathURLs = null;
|
|
||||||
}
|
|
||||||
this.unopenedURLs = unopenedURLs;
|
|
||||||
this.pathURLs = pathURLs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object fetchField(final Class<?> clazz, final Object object, final String name) throws NoSuchFieldException {
|
|
||||||
Field field = clazz.getDeclaredField(name);
|
|
||||||
long offset = UNSAFE.objectFieldOffset(field);
|
|
||||||
return UNSAFE.getObject(object, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addURL(@Nonnull URL url) {
|
|
||||||
this.unopenedURLs.add(url);
|
|
||||||
this.pathURLs.add(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Noop extends URLClassLoaderAccess {
|
|
||||||
private static final Noop INSTANCE = new Noop();
|
|
||||||
|
|
||||||
private Noop() {
|
|
||||||
super(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addURL(@Nonnull URL url) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) <2022> <XiaoMoMi>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package net.momirealms.customcrops.integrations.skill;
|
package net.momirealms.customcrops.integrations.skill;
|
||||||
|
|
||||||
import com.archyx.aureliumskills.api.AureliumAPI;
|
import com.archyx.aureliumskills.api.AureliumAPI;
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) <2022> <XiaoMoMi>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package net.momirealms.customcrops.integrations.skill;
|
package net.momirealms.customcrops.integrations.skill;
|
||||||
|
|
||||||
import net.Indyuce.mmocore.experience.EXPSource;
|
import net.Indyuce.mmocore.experience.EXPSource;
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) <2022> <XiaoMoMi>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package net.momirealms.customcrops.integrations.skill;
|
package net.momirealms.customcrops.integrations.skill;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public interface SkillXP {
|
public interface SkillXP {
|
||||||
void addXp(Player player, double amount);
|
void addXp(Player player, double amount);
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) <2022> <XiaoMoMi>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package net.momirealms.customcrops.integrations.skill;
|
package net.momirealms.customcrops.integrations.skill;
|
||||||
|
|
||||||
import com.gmail.nossr50.api.ExperienceAPI;
|
import com.gmail.nossr50.api.ExperienceAPI;
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ public class BreakBlock implements Listener {
|
|||||||
normalDrop(cropInstance, random, itemLoc, world);
|
normalDrop(cropInstance, random, itemLoc, world);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, ()-> {
|
Bukkit.getScheduler().callSyncMethod(CustomCrops.instance, ()-> {
|
||||||
@@ -124,7 +123,6 @@ public class BreakBlock implements Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(namespacedId.equalsIgnoreCase(ConfigReader.Basic.watered_pot) || namespacedId.equalsIgnoreCase(ConfigReader.Basic.pot)){
|
else if(namespacedId.equalsIgnoreCase(ConfigReader.Basic.watered_pot) || namespacedId.equalsIgnoreCase(ConfigReader.Basic.pot)){
|
||||||
@@ -138,9 +136,8 @@ public class BreakBlock implements Listener {
|
|||||||
if(CustomBlock.byAlreadyPlaced(blockUp) != null){
|
if(CustomBlock.byAlreadyPlaced(blockUp) != null){
|
||||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(blockUp);
|
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(blockUp);
|
||||||
String cropNamespacedId = customBlock.getNamespacedID();
|
String cropNamespacedId = customBlock.getNamespacedID();
|
||||||
if(cropNamespacedId.contains("_stage_")){
|
if(cropNamespacedId.contains("_stage_") && !cropNamespacedId.equals(ConfigReader.Basic.dead)){
|
||||||
CustomBlock.remove(location);
|
CustomBlock.remove(location);
|
||||||
if (cropNamespacedId.equals(ConfigReader.Basic.dead)) return;
|
|
||||||
if (ConfigReader.Config.quality){
|
if (ConfigReader.Config.quality){
|
||||||
String[] cropNameList = StringUtils.split(StringUtils.split(cropNamespacedId, ":")[1], "_");
|
String[] cropNameList = StringUtils.split(StringUtils.split(cropNamespacedId, ":")[1], "_");
|
||||||
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
|
||||||
@@ -183,6 +180,13 @@ public class BreakBlock implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 没有品质肥料下的普通掉落
|
||||||
|
* @param cropInstance 农作物
|
||||||
|
* @param random 随机农作物数量
|
||||||
|
* @param itemLoc 掉落物位置
|
||||||
|
* @param world 世界
|
||||||
|
*/
|
||||||
static void normalDrop(CropInstance cropInstance, int random, Location itemLoc, World world) {
|
static void normalDrop(CropInstance cropInstance, int random, Location itemLoc, World world) {
|
||||||
for (int i = 0; i < random; i++){
|
for (int i = 0; i < random; i++){
|
||||||
double ran = Math.random();
|
double ran = Math.random();
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import net.momirealms.customcrops.utils.Sprinkler;
|
|||||||
import net.momirealms.customcrops.utils.WateringCan;
|
import net.momirealms.customcrops.utils.WateringCan;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Particle;
|
|
||||||
import org.bukkit.entity.ArmorStand;
|
import org.bukkit.entity.ArmorStand;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -160,6 +159,15 @@ public class InteractEntity implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某个洒水器的水量
|
||||||
|
* @param location 洒水器位置
|
||||||
|
* @param world 世界
|
||||||
|
* @param x 坐标
|
||||||
|
* @param z 坐标
|
||||||
|
* @param sprinkler 洒水器类型
|
||||||
|
* @return 水量
|
||||||
|
*/
|
||||||
private int getCurrentWater(Location location, String world, int x, int z, Sprinkler sprinkler) {
|
private int getCurrentWater(Location location, String world, int x, int z, Sprinkler sprinkler) {
|
||||||
int currentWater;
|
int currentWater;
|
||||||
if (sprinkler != null){
|
if (sprinkler != null){
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ public class RightClick implements Listener {
|
|||||||
Action action = event.getAction();
|
Action action = event.getAction();
|
||||||
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK){
|
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK){
|
||||||
ItemStack itemStack = event.getItem();
|
ItemStack itemStack = event.getItem();
|
||||||
if (itemStack != null){
|
if (itemStack != null && itemStack.getType() != Material.AIR){
|
||||||
if (itemStack.getType() == Material.AIR) return;
|
|
||||||
NBTItem nbtItem = new NBTItem(itemStack);
|
NBTItem nbtItem = new NBTItem(itemStack);
|
||||||
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
|
||||||
if (nbtCompound != null){
|
if (nbtCompound != null){
|
||||||
@@ -145,9 +144,8 @@ public class RightClick implements Listener {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Optional<WateringCan> can = Optional.ofNullable(ConfigReader.CANS.get(id));
|
WateringCan wateringCan = ConfigReader.CANS.get(id);
|
||||||
if (can.isPresent()){
|
if (wateringCan != null){
|
||||||
WateringCan wateringCan = can.get();
|
|
||||||
int water = nbtItem.getInteger("WaterAmount");
|
int water = nbtItem.getInteger("WaterAmount");
|
||||||
List<Block> lineOfSight = player.getLineOfSight(null, 5);
|
List<Block> lineOfSight = player.getLineOfSight(null, 5);
|
||||||
for (Block block : lineOfSight) {
|
for (Block block : lineOfSight) {
|
||||||
@@ -226,9 +224,8 @@ public class RightClick implements Listener {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Optional<Fertilizer> fertilize = Optional.ofNullable(ConfigReader.FERTILIZERS.get(id));
|
Fertilizer fertilizerConfig = ConfigReader.FERTILIZERS.get(id);
|
||||||
if (fertilize.isPresent() && action == Action.RIGHT_CLICK_BLOCK){
|
if (fertilizerConfig != null && action == Action.RIGHT_CLICK_BLOCK){
|
||||||
Fertilizer fertilizerConfig = fertilize.get();
|
|
||||||
Block block = event.getClickedBlock();
|
Block block = event.getClickedBlock();
|
||||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||||
if (customBlock == null) return;
|
if (customBlock == null) return;
|
||||||
@@ -264,8 +261,8 @@ public class RightClick implements Listener {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Optional<Sprinkler> sprinkler = Optional.ofNullable(ConfigReader.SPRINKLERS.get(id));
|
Sprinkler sprinkler = ConfigReader.SPRINKLERS.get(id);
|
||||||
if (sprinkler.isPresent() && action == Action.RIGHT_CLICK_BLOCK && event.getBlockFace() == BlockFace.UP){
|
if (sprinkler != null && action == Action.RIGHT_CLICK_BLOCK && event.getBlockFace() == BlockFace.UP){
|
||||||
Location location = event.getClickedBlock().getLocation();
|
Location location = event.getClickedBlock().getLocation();
|
||||||
for (Integration integration : ConfigReader.Config.integration){
|
for (Integration integration : ConfigReader.Config.integration){
|
||||||
if (!integration.canPlace(location, player)) return;
|
if (!integration.canPlace(location, player)) return;
|
||||||
@@ -277,10 +274,10 @@ public class RightClick implements Listener {
|
|||||||
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.sprinkler_limit.replace("{max}", String.valueOf(ConfigReader.Config.sprinklerLimit)));
|
AdventureManager.playerMessage(player, ConfigReader.Message.prefix + ConfigReader.Message.sprinkler_limit.replace("{max}", String.valueOf(ConfigReader.Config.sprinklerLimit)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Sprinkler sprinklerData = new Sprinkler(sprinkler.get().getRange(), 0);
|
Sprinkler sprinklerData = new Sprinkler(sprinkler.getRange(), 0);
|
||||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||||
SprinklerManager.Cache.put(location.add(0,1,0), sprinklerData);
|
SprinklerManager.Cache.put(location.add(0,1,0), sprinklerData);
|
||||||
IAFurniture.placeFurniture(sprinkler.get().getNamespacedID_2(),location);
|
IAFurniture.placeFurniture(sprinkler.getNamespacedID_2(),location);
|
||||||
AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey);
|
AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -318,17 +315,27 @@ public class RightClick implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(ConfigReader.Config.rightClickHarvest && !ConfigReader.Config.needEmptyHand){
|
else if(ConfigReader.Config.rightClickHarvest && !ConfigReader.Config.needEmptyHand){
|
||||||
rightClickHarvest(event, player);
|
Block block = event.getClickedBlock();
|
||||||
|
if (block != null){
|
||||||
|
rightClickHarvest(block, player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ConfigReader.Config.rightClickHarvest && action == Action.RIGHT_CLICK_BLOCK) {
|
else if (ConfigReader.Config.rightClickHarvest && action == Action.RIGHT_CLICK_BLOCK) {
|
||||||
rightClickHarvest(event, player);
|
Block block = event.getClickedBlock();
|
||||||
|
if (block != null){
|
||||||
|
rightClickHarvest(block, player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rightClickHarvest(PlayerInteractEvent event, Player player) {
|
/**
|
||||||
Block block = event.getClickedBlock();
|
* 右键收获判定
|
||||||
|
* @param block 农作物方块
|
||||||
|
* @param player 玩家
|
||||||
|
*/
|
||||||
|
private void rightClickHarvest(Block block, Player player) {
|
||||||
Location location = block.getLocation();
|
Location location = block.getLocation();
|
||||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||||
if (customBlock == null) return;
|
if (customBlock == null) return;
|
||||||
@@ -357,6 +364,11 @@ public class RightClick implements Listener {
|
|||||||
if (ConfigReader.Config.skillXP != null && cropInstance.getSkillXP() != 0){
|
if (ConfigReader.Config.skillXP != null && cropInstance.getSkillXP() != 0){
|
||||||
ConfigReader.Config.skillXP.addXp(player, cropInstance.getSkillXP());
|
ConfigReader.Config.skillXP.addXp(player, cropInstance.getSkillXP());
|
||||||
}
|
}
|
||||||
|
if (cropInstance.doesDropIALoot()){
|
||||||
|
customBlock.getLoot().forEach(itemStack -> {
|
||||||
|
location.getWorld().dropItem(location.clone().add(0.5,0.2,0.5), itemStack);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (fertilizer != null){
|
if (fertilizer != null){
|
||||||
if (fertilizer instanceof QualityCrop qualityCrop){
|
if (fertilizer instanceof QualityCrop qualityCrop){
|
||||||
int[] weights = qualityCrop.getChance();
|
int[] weights = qualityCrop.getChance();
|
||||||
@@ -398,6 +410,11 @@ public class RightClick implements Listener {
|
|||||||
coolDown.remove(event.getPlayer());
|
coolDown.remove(event.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加肥料
|
||||||
|
* @param fertilizerConfig 肥料配置
|
||||||
|
* @param location 种植盆位置
|
||||||
|
*/
|
||||||
private void addFertilizer(Fertilizer fertilizerConfig, Location location) {
|
private void addFertilizer(Fertilizer fertilizerConfig, Location location) {
|
||||||
if (fertilizerConfig instanceof QualityCrop config){
|
if (fertilizerConfig instanceof QualityCrop config){
|
||||||
QualityCrop qualityCrop = new QualityCrop(config.getKey(), config.getTimes(), config.getChance(), config.isBefore());
|
QualityCrop qualityCrop = new QualityCrop(config.getKey(), config.getTimes(), config.getChance(), config.isBefore());
|
||||||
@@ -411,6 +428,13 @@ public class RightClick implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水壶浇水判定
|
||||||
|
* @param width 宽度
|
||||||
|
* @param length 长度
|
||||||
|
* @param location 位置
|
||||||
|
* @param yaw 视角
|
||||||
|
*/
|
||||||
private void waterPot(int width, int length, Location location, float yaw){
|
private void waterPot(int width, int length, Location location, float yaw){
|
||||||
if (ConfigReader.Config.hasParticle){
|
if (ConfigReader.Config.hasParticle){
|
||||||
location.getWorld().spawnParticle(Particle.WATER_SPLASH, location.clone().add(0.5,1.2,0.5),15,0.1,0.1, 0.1);
|
location.getWorld().spawnParticle(Particle.WATER_SPLASH, location.clone().add(0.5,1.2,0.5),15,0.1,0.1, 0.1);
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ import java.time.Duration;
|
|||||||
|
|
||||||
public class AdventureManager {
|
public class AdventureManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送控制台信息
|
||||||
|
* @param s 文本
|
||||||
|
*/
|
||||||
public static void consoleMessage(String s) {
|
public static void consoleMessage(String s) {
|
||||||
Audience au = CustomCrops.adventure.sender(Bukkit.getConsoleSender());
|
Audience au = CustomCrops.adventure.sender(Bukkit.getConsoleSender());
|
||||||
MiniMessage mm = MiniMessage.miniMessage();
|
MiniMessage mm = MiniMessage.miniMessage();
|
||||||
@@ -38,6 +42,11 @@ public class AdventureManager {
|
|||||||
au.sendMessage(parsed);
|
au.sendMessage(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送玩家信息
|
||||||
|
* @param player 玩家
|
||||||
|
* @param s 文本
|
||||||
|
*/
|
||||||
public static void playerMessage(Player player, String s) {
|
public static void playerMessage(Player player, String s) {
|
||||||
Audience au = CustomCrops.adventure.player(player);
|
Audience au = CustomCrops.adventure.player(player);
|
||||||
MiniMessage mm = MiniMessage.miniMessage();
|
MiniMessage mm = MiniMessage.miniMessage();
|
||||||
@@ -45,6 +54,15 @@ public class AdventureManager {
|
|||||||
au.sendMessage(parsed);
|
au.sendMessage(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送玩家标题
|
||||||
|
* @param player 玩家
|
||||||
|
* @param s1 主标题
|
||||||
|
* @param s2 副标题
|
||||||
|
* @param in 淡入时间
|
||||||
|
* @param duration 停留时间
|
||||||
|
* @param out 淡出时间
|
||||||
|
*/
|
||||||
public static void playerTitle(Player player, String s1, String s2, int in, int duration, int out) {
|
public static void playerTitle(Player player, String s1, String s2, int in, int duration, int out) {
|
||||||
Audience au = CustomCrops.adventure.player(player);
|
Audience au = CustomCrops.adventure.player(player);
|
||||||
MiniMessage mm = MiniMessage.miniMessage();
|
MiniMessage mm = MiniMessage.miniMessage();
|
||||||
@@ -53,12 +71,23 @@ public class AdventureManager {
|
|||||||
au.showTitle(title);
|
au.showTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送动作消息
|
||||||
|
* @param player 玩家
|
||||||
|
* @param s 文本
|
||||||
|
*/
|
||||||
public static void playerActionbar(Player player, String s) {
|
public static void playerActionbar(Player player, String s) {
|
||||||
Audience au = CustomCrops.adventure.player(player);
|
Audience au = CustomCrops.adventure.player(player);
|
||||||
MiniMessage mm = MiniMessage.miniMessage();
|
MiniMessage mm = MiniMessage.miniMessage();
|
||||||
au.sendActionBar(mm.deserialize(s));
|
au.sendActionBar(mm.deserialize(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送声音
|
||||||
|
* @param player 玩家
|
||||||
|
* @param source 来源
|
||||||
|
* @param key 键
|
||||||
|
*/
|
||||||
public static void playerSound(Player player, Sound.Source source, Key key) {
|
public static void playerSound(Player player, Sound.Source source, Key key) {
|
||||||
Sound sound = Sound.sound(key, source, 1, 1);
|
Sound sound = Sound.sound(key, source, 1, 1);
|
||||||
Audience au = CustomCrops.adventure.player(player);
|
Audience au = CustomCrops.adventure.player(player);
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ import java.util.List;
|
|||||||
|
|
||||||
public class BackUp {
|
public class BackUp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备份全部文件
|
||||||
|
*/
|
||||||
public static void backUpData(){
|
public static void backUpData(){
|
||||||
|
|
||||||
List<String> files = Arrays.asList("crop","sprinkler","pot","season");
|
List<String> files = Arrays.asList("crop","sprinkler","pot","season");
|
||||||
@@ -49,6 +52,12 @@ public class BackUp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制某个文件
|
||||||
|
* @param file_from 源文件
|
||||||
|
* @param file_to 目标文件
|
||||||
|
* @throws IOException IO异常
|
||||||
|
*/
|
||||||
private static void backUp(File file_from, File file_to) throws IOException {
|
private static void backUp(File file_from, File file_to) throws IOException {
|
||||||
if(!file_to.exists()){
|
if(!file_to.exists()){
|
||||||
file_to.getParentFile().mkdirs();
|
file_to.getParentFile().mkdirs();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package net.momirealms.customcrops.utils;
|
package net.momirealms.customcrops.utils;
|
||||||
|
|
||||||
import net.momirealms.customcrops.integrations.skill.SkillXP;
|
|
||||||
import net.momirealms.customcrops.requirements.Requirement;
|
import net.momirealms.customcrops.requirements.Requirement;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -35,7 +34,9 @@ public class CropInstance {
|
|||||||
private String quality_2;
|
private String quality_2;
|
||||||
private String quality_3;
|
private String quality_3;
|
||||||
private double skillXP;
|
private double skillXP;
|
||||||
|
private boolean dropIALoot;
|
||||||
private List<String> commands;
|
private List<String> commands;
|
||||||
|
private double growChance;
|
||||||
|
|
||||||
public CropInstance(int min, int max){
|
public CropInstance(int min, int max){
|
||||||
this.min = min;
|
this.min = min;
|
||||||
@@ -58,6 +59,8 @@ public class CropInstance {
|
|||||||
public int getMin() { return min; }
|
public int getMin() { return min; }
|
||||||
public List<String> getCommands() { return commands; }
|
public List<String> getCommands() { return commands; }
|
||||||
public double getSkillXP() {return skillXP;}
|
public double getSkillXP() {return skillXP;}
|
||||||
|
public boolean doesDropIALoot() {return dropIALoot;}
|
||||||
|
public double getGrowChance() {return growChance;}
|
||||||
|
|
||||||
public void setReturnStage(String stage){ this.returnStage = stage; }
|
public void setReturnStage(String stage){ this.returnStage = stage; }
|
||||||
public void setGiant(String giant) { this.giant = giant; }
|
public void setGiant(String giant) { this.giant = giant; }
|
||||||
@@ -69,4 +72,6 @@ public class CropInstance {
|
|||||||
public void setQuality_3(String quality_3) { this.quality_3 = quality_3; }
|
public void setQuality_3(String quality_3) { this.quality_3 = quality_3; }
|
||||||
public void setCommands(List<String> commands) { this.commands = commands; }
|
public void setCommands(List<String> commands) { this.commands = commands; }
|
||||||
public void setSkillXP(double skillXP) {this.skillXP = skillXP;}
|
public void setSkillXP(double skillXP) {this.skillXP = skillXP;}
|
||||||
|
public void setDropIALoot(boolean dropIALoot) {this.dropIALoot = dropIALoot;}
|
||||||
|
public void setGrowChance(double growChance) {this.growChance = growChance;}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ public class HoloUtil {
|
|||||||
|
|
||||||
public static HashMap<Location, Entity> cache = new HashMap<>();
|
public static HashMap<Location, Entity> cache = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对指定玩家展示在指定位置的盔甲架
|
||||||
|
* @param text 文本
|
||||||
|
* @param player 玩家
|
||||||
|
* @param location 位置
|
||||||
|
* @param duration 持续时间
|
||||||
|
*/
|
||||||
public static void showHolo(String text, Player player, Location location, int duration){
|
public static void showHolo(String text, Player player, Location location, int duration){
|
||||||
|
|
||||||
ArmorStand entity = location.getWorld().spawn(location, ArmorStand.class, a -> {
|
ArmorStand entity = location.getWorld().spawn(location, ArmorStand.class, a -> {
|
||||||
|
|||||||
@@ -26,10 +26,21 @@ import org.bukkit.entity.Entity;
|
|||||||
|
|
||||||
public class IAFurniture {
|
public class IAFurniture {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在指定位置放置家具
|
||||||
|
* @param name 物品名
|
||||||
|
* @param location 位置
|
||||||
|
*/
|
||||||
public static void placeFurniture(String name, Location location){
|
public static void placeFurniture(String name, Location location){
|
||||||
CustomFurniture.spawn(name, location.getBlock());
|
CustomFurniture.spawn(name, location.getBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断指定位置的盔甲架是不是洒水器
|
||||||
|
* @param location 位置
|
||||||
|
* @param world 世界
|
||||||
|
* @return 是/否
|
||||||
|
*/
|
||||||
public static boolean getFromLocation(Location location, World world){
|
public static boolean getFromLocation(Location location, World world){
|
||||||
for(Entity entity : world.getNearbyEntities(location,0,0,0)){
|
for(Entity entity : world.getNearbyEntities(location,0,0,0)){
|
||||||
if(entity instanceof ArmorStand armorStand){
|
if(entity instanceof ArmorStand armorStand){
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) <2022> <XiaoMoMi>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.momirealms.customcrops.utils;
|
|
||||||
|
|
||||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
|
||||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class NBTUtil {
|
|
||||||
|
|
||||||
private final Map<?,?> nbt;
|
|
||||||
private final NBTItem nbtItem;
|
|
||||||
|
|
||||||
public NBTUtil(Map<?,?> nbt, ItemStack itemStack){
|
|
||||||
this.nbt = nbt;
|
|
||||||
this.nbtItem = new NBTItem(itemStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NBTItem getNBTItem(){
|
|
||||||
nbt.keySet().forEach(key -> {
|
|
||||||
if (nbt.get(key) instanceof Map<?,?> map){
|
|
||||||
nbtItem.addCompound((String) key);
|
|
||||||
setTags(map, nbtItem.getCompound((String) key));
|
|
||||||
}else {
|
|
||||||
setNbt(nbtItem, (String) key, nbt.get(key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this.nbtItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTags(Map<?,?> map, NBTCompound nbtCompound){
|
|
||||||
map.keySet().forEach(key -> {
|
|
||||||
if (map.get(key) instanceof Map map2){
|
|
||||||
nbtCompound.addCompound((String) key);
|
|
||||||
setTags(map2, nbtCompound.getCompound((String) key));
|
|
||||||
}else {
|
|
||||||
setNbt(nbtCompound, (String) key, map.get(key));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setNbt(NBTCompound nbtCompound, String key, Object value){
|
|
||||||
if (value instanceof String string){
|
|
||||||
if (string.startsWith("(Int) ")){
|
|
||||||
nbtCompound.setInteger(key, Integer.valueOf(string.substring(6)));
|
|
||||||
}else if (string.startsWith("(String) ")){
|
|
||||||
nbtCompound.setString(key, string.substring(9));
|
|
||||||
}else if (string.startsWith("(Long) ")){
|
|
||||||
nbtCompound.setLong(key, Long.valueOf(string.substring(7)));
|
|
||||||
}else if (string.startsWith("(Float) ")){
|
|
||||||
nbtCompound.setFloat(key, Float.valueOf(string.substring(8)));
|
|
||||||
} else if (string.startsWith("(Double) ")){
|
|
||||||
nbtCompound.setDouble(key, Double.valueOf(string.substring(9)));
|
|
||||||
}else if (string.startsWith("(Short) ")){
|
|
||||||
nbtCompound.setShort(key, Short.valueOf(string.substring(8)));
|
|
||||||
}else if (string.startsWith("(Boolean) ")){
|
|
||||||
nbtCompound.setBoolean(key, Boolean.valueOf(string.substring(10)));
|
|
||||||
}else if (string.startsWith("(UUID) ")){
|
|
||||||
nbtCompound.setUUID(key, UUID.fromString(string.substring(7)));
|
|
||||||
}else if (string.startsWith("(Byte) ")){
|
|
||||||
nbtCompound.setByte(key, Byte.valueOf(string.substring(7)));
|
|
||||||
}else {
|
|
||||||
nbtCompound.setString(key, string);
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
try {
|
|
||||||
nbtCompound.setInteger(key, (Integer) value);
|
|
||||||
}catch (ClassCastException e){
|
|
||||||
e.printStackTrace();
|
|
||||||
AdventureManager.consoleMessage("<red>[CustomCrops] 非Int类型数字必须加上强制转换标识!</red>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -35,25 +35,19 @@ public class SimpleLocation {
|
|||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Location转换为SimpleLocation
|
||||||
|
* @param location Location
|
||||||
|
* @return SimpleLocation
|
||||||
|
*/
|
||||||
public static SimpleLocation fromLocation(Location location){
|
public static SimpleLocation fromLocation(Location location){
|
||||||
return new SimpleLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
return new SimpleLocation(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {return x;}
|
||||||
return x;
|
public int getZ() {return z;}
|
||||||
}
|
public int getY() {return y;}
|
||||||
|
public String getWorldName() {return worldName;}
|
||||||
public int getZ() {
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWorldName() {
|
|
||||||
return worldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
|
|||||||
@@ -29,29 +29,13 @@ public class Sprinkler {
|
|||||||
this.range = range;
|
this.range = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWater() {
|
public int getWater() {return water;}
|
||||||
return water;
|
public String getNamespacedID_1() {return namespacedID_1;}
|
||||||
}
|
public String getNamespacedID_2() {return namespacedID_2;}
|
||||||
public String getNamespacedID_1() {
|
public int getRange() {return range;}
|
||||||
return namespacedID_1;
|
|
||||||
}
|
|
||||||
public String getNamespacedID_2() {
|
|
||||||
return namespacedID_2;
|
|
||||||
}
|
|
||||||
public int getRange() {
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRange(int range) {
|
public void setRange(int range) {this.range = range;}
|
||||||
this.range = range;
|
public void setNamespacedID_2(String namespacedID_2) {this.namespacedID_2 = namespacedID_2;}
|
||||||
}
|
public void setNamespacedID_1(String namespacedID_1) {this.namespacedID_1 = namespacedID_1;}
|
||||||
public void setNamespacedID_2(String namespacedID_2) {
|
public void setWater(int water) {this.water = water;}
|
||||||
this.namespacedID_2 = namespacedID_2;
|
|
||||||
}
|
|
||||||
public void setNamespacedID_1(String namespacedID_1) {
|
|
||||||
this.namespacedID_1 = namespacedID_1;
|
|
||||||
}
|
|
||||||
public void setWater(int water) {
|
|
||||||
this.water = water;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,21 @@
|
|||||||
|
|
||||||
crops:
|
crops:
|
||||||
tomato:
|
tomato:
|
||||||
|
|
||||||
amount: 1~4
|
amount: 1~4
|
||||||
quality:
|
quality:
|
||||||
1: customcrops:tomato
|
1: customcrops:tomato
|
||||||
2: customcrops:tomato_silver_star
|
2: customcrops:tomato_silver_star
|
||||||
3: customcrops:tomato_golden_star
|
3: customcrops:tomato_golden_star
|
||||||
|
|
||||||
|
#optional
|
||||||
|
#The chance that a crop grow a stage at grow time
|
||||||
|
grow-chance: 0.9
|
||||||
|
|
||||||
|
#When harvesting, should the crop drop the loots from ItemsAdder too
|
||||||
|
#This is useful for droping seeds and other items
|
||||||
|
drop-ia-loots: false
|
||||||
|
|
||||||
#optional
|
#optional
|
||||||
#Overweight
|
#Overweight
|
||||||
gigantic:
|
gigantic:
|
||||||
|
|||||||
Reference in New Issue
Block a user