diff --git a/CONTRIBUTING.cn.md b/CONTRIBUTING.cn.md
index 466037d7ac..b924cf37c3 100644
--- a/CONTRIBUTING.cn.md
+++ b/CONTRIBUTING.cn.md
@@ -8,6 +8,11 @@
2. 导入配色方案(可选)
- [此处查看](https://server.cjsah.net:1002/self/Cjsah.v15.icls)
- `设置` -> `编辑器` -> `配色方案` -> `导入方案`
+3. 添加 `CheckStyle-IDEA` 插件(可选)
+ - `插件` -> `Marketplace`
+ - 搜索由 `Jamie Shiell` 制作的 `CheckStyle-IDEA` 插件并应用
+ - `设置` -> `工具` -> `CheckStyle` -> `Configuration File` -> `+`/`添加` -> 选择项目根目录下的 `style.xml` 文件
+ - `设置` -> `工具` -> `CheckStyle` -> `Configuration File` -> 将除刚添加的条目外的其它条目取消勾选
## 各类注解的使用
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 85823318fc..7d92cf266c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,6 +8,11 @@
2. Import color scheme (optional)
- [HERE TO VIEW](https://server.cjsah.net:1002/self/Cjsah.v15.icls)
- `Settings` -> `Editor` -> `Color Scheme` -> `Import Scheme`
+3. Add `CheckStyle-IDEA` plugin (optional)
+ - `Plugins` -> `Marketplace`
+ - Search for `CheckStyle-IDEA` plugin, made by `Jamie Shiell` and apply it
+ - `Settings` -> `Tools` -> `CheckStyle` -> `Configuration File` -> `+`/`Add` -> Choose the `style.xml` file in the root folder of this project
+ - `Settings` -> `Tools` -> `CheckStyle` -> `Configuration File` -> Uncheck other entries except the entry added before
## The use of various annotations
diff --git a/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/src/generated/resources/assets/anvilcraft/lang/en_ud.json
index 61ee5d09b7..f4dc2c9515 100644
--- a/src/generated/resources/assets/anvilcraft/lang/en_ud.json
+++ b/src/generated/resources/assets/anvilcraft/lang/en_ud.json
@@ -26,7 +26,7 @@
"advancements.anvilcraft.four281.description": "ǝɔı ǝnןq ǝʞɐɯ oʇ ǝɔı pǝʞɔɐd ɟo sǝɔǝıd oʍʇ ssǝɹdɯoɔ oʇ ןıʌuɐ uɐ ǝsn uǝɥʇ puɐ 'ǝɔı pǝʞɔɐd ǝʞɐɯ oʇ ǝɔı ɟo sǝɔǝıd oʍʇ ssǝɹdɯoɔ oʇ ןıʌuɐ uɐ ǝs∩",
"advancements.anvilcraft.four281.title": "Ɩ8 oʇ ㄣ",
"advancements.anvilcraft.frost_metal.description": "ןɐʇǝɯ ʇsoɹɟ ʎuɐ uıɐʇqO",
- "advancements.anvilcraft.frost_metal.title": "ʎɐp ɐ uı ʇןınq ʇou sɐʍ ǝɯoᴚ",
+ "advancements.anvilcraft.frost_metal.title": "pןoɔ s,ʎɐp ǝuo uı uǝzoɹɟ ʇou sɐʍ ɹǝʌıᴚ",
"advancements.anvilcraft.gem_transform.description": "ʞɔoןq ɯǝb ǝʞɐɯ oʇ dɹɐʍ ǝɯıʇ buısn puɐ uoɹpןnɐɔ ɯǝb ʇןǝɯ oʇuı ɯǝb buıddoɹᗡ",
"advancements.anvilcraft.gem_transform.title": "ɯɹoɟsuɐɹʇ ɯǝ⅁",
"advancements.anvilcraft.geode.description": "ǝpoǝb ɥʇıʍ ǝpoǝb ʇsʎɥʇǝɯɐ buıɹoןdxǝ 'ǝpoǝb uıɐʇqO",
@@ -97,7 +97,7 @@
"advancements.anvilcraft.tai_shang_wang_qing.title": "suoıʇoɯǝ puoʎǝq sןɐʇɹoɯɯI",
"advancements.anvilcraft.topaz.description": "zɐdoʇ ɥʇıʍ poɹ buıuʇɥbıן ǝɥʇ uo buıuʇɥbıן uoɯɯnS",
"advancements.anvilcraft.topaz.title": "buıuʇɥbıן ɟo ɹǝʍod ǝɥ⟘",
- "advancements.anvilcraft.transcendence.description": "ʞɔoןq ɯnıpuǝɔsuɐɹʇ ʇɟɐɹɔ oʇ ʞɔoןq ןɐʇǝɯ ɹǝqɯǝ pǝʇɐǝɥɹǝʌo uɐ oʇuı ʇobuı ɯnıuoɹʇnǝu pǝbɹɐɥɔ uɐ buıʇɔǝظuI",
+ "advancements.anvilcraft.transcendence.description": "ɯnıpuǝɔsuɐɹʇ ʇɟɐɹɔ oʇ ʞɔoןq ןɐʇǝɯ ɹǝqɯǝ pǝʇɐǝɥɹǝʌo uɐ oʇuı ʇobuı ɯnıuoɹʇnǝu pǝbɹɐɥɔ uɐ buıʇɔǝظuI",
"advancements.anvilcraft.transcendence.title": "ǝɔuǝpuǝɔsuɐɹ⟘",
"advancements.anvilcraft.vanilla_iron_plate.description": "ǝʇɐןd ǝɹnssǝɹd pǝʇɥbıǝʍ ʎʌɐǝɥ uıɐʇqo oʇ ɯɹoɟʇɐןd buıdɯɐʇs ǝɥʇ uo sʇobuı uoɹı ɥsɐɯS",
"advancements.anvilcraft.vanilla_iron_plate.title": "ǝʇɐןd uoɹı ɐןןıuɐΛ",
@@ -307,8 +307,8 @@
"block.anvilcraft.ember_metal_block": "ןɐʇǝW ɹǝqɯƎ ɟo ʞɔoןᗺ",
"block.anvilcraft.ember_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ɹǝqɯƎ",
"block.anvilcraft.end_dust": "ʇsnᗡ puƎ",
- "block.anvilcraft.exp_cauldron": "uoɹpןnɐƆ dxƎ",
"block.anvilcraft.exp_fluid": "pınןℲ dxƎ",
+ "block.anvilcraft.exp_fluid_cauldron": "uoɹpןnɐƆ pınןℲ dxƎ",
"block.anvilcraft.exp_gem_block": "ɯǝ⅁ ǝɔuǝıɹǝdxƎ ɟo ʞɔoןᗺ",
"block.anvilcraft.exposed_copper_pressure_plate": "ǝʇɐןԀ ǝɹnssǝɹԀ ɹǝddoƆ pǝsodxƎ",
"block.anvilcraft.ferrite_core_magnet_block": "ʇǝubɐW ɟo ʞɔoןᗺ pǝɹoƆ-ǝʇıɹɹǝℲ",
@@ -992,11 +992,12 @@
"screen.anvilcraft.integration_screen.category.interaction": "uoıʇɔɐɹǝʇuI",
"screen.anvilcraft.integration_screen.category.modify": "ʎɟıpoW",
"screen.anvilcraft.integration_screen.category.recipe_query": "ʎɹǝnὉ ǝdıɔǝᴚ",
- "screen.anvilcraft.integration_screen.extra": ":poW ɐɹʇxƎ",
+ "screen.anvilcraft.integration_screen.extra": ":pɐoןuʍoᗡ ɐɹʇxƎ",
"screen.anvilcraft.integration_screen.loaded": "pǝpɐoꞀ",
"screen.anvilcraft.integration_screen.not_found": "pǝןןɐʇsuI ʇoN",
"screen.anvilcraft.integration_screen.not_loaded": "pǝpuǝɯɯoɔǝᴚ",
- "screen.anvilcraft.integration_screen.target": ":poW ʇǝbɹɐ⟘",
+ "screen.anvilcraft.integration_screen.note": "˙uoʇʇnq ǝɥʇ buıʞɔıןɔ ʎq pǝssǝɔɔɐ ǝq uɐɔ puɐ pǝpıʌoɹd uǝǝq ǝʌɐɥ sʞuıן pɐoןuʍoᗡ ˙pǝɹınbǝɹ ǝɹɐ spoɯ ןɐuoıʇıppɐ %d ɟo ןɐʇoʇ Ɐ ˙poɯ sıɥʇ ɯoɹɟ ʇı ɹoɟ uo-ppɐ ʎʇıןıqıʇɐdɯoɔ ǝɥʇ pɐoןuʍop uǝɥʇ 'poɯ ןɐnuɐɯ ʎʇɹɐd-pɹıɥʇ ɐ pɐoןuʍop puɐ ǝsooɥɔ ʇsɹıɟ 'ןɐnuɐɯ ǝɥʇ ssǝɔɔɐ o⟘",
+ "screen.anvilcraft.integration_screen.target": ":pɐoןuʍoᗡ poW uıɐW",
"screen.anvilcraft.integration_screen.title": "suoıʇɐɹbǝʇuI",
"screen.anvilcraft.integration_screen.url.curseforge": "ǝbɹoℲǝsɹnƆ",
"screen.anvilcraft.integration_screen.url.github": "ʎɹoʇısodǝᴚ qnɥʇı⅁",
diff --git a/src/generated/resources/assets/anvilcraft/lang/en_us.json b/src/generated/resources/assets/anvilcraft/lang/en_us.json
index cca9e4b8a4..139e8c3b90 100644
--- a/src/generated/resources/assets/anvilcraft/lang/en_us.json
+++ b/src/generated/resources/assets/anvilcraft/lang/en_us.json
@@ -26,7 +26,7 @@
"advancements.anvilcraft.four281.description": "Use an anvil to compress two pieces of ice to make packed ice, and then use an anvil to compress two pieces of packed ice to make blue ice",
"advancements.anvilcraft.four281.title": "4 to 81",
"advancements.anvilcraft.frost_metal.description": "Obtain any frost metal",
- "advancements.anvilcraft.frost_metal.title": "Rome was not built in a day",
+ "advancements.anvilcraft.frost_metal.title": "River was not frozen in one day's cold",
"advancements.anvilcraft.gem_transform.description": "Dropping gem into melt gem cauldron and using time warp to make gem block",
"advancements.anvilcraft.gem_transform.title": "Gem transform",
"advancements.anvilcraft.geode.description": "Obtain geode, exploring amethyst geode with geode",
@@ -97,7 +97,7 @@
"advancements.anvilcraft.tai_shang_wang_qing.title": "Immortals beyond emotions",
"advancements.anvilcraft.topaz.description": "Summon lightning on the lightning rod with topaz",
"advancements.anvilcraft.topaz.title": "The power of lightning",
- "advancements.anvilcraft.transcendence.description": "Injecting an charged neutronium ingot into an overheated ember metal block to craft transcendium block",
+ "advancements.anvilcraft.transcendence.description": "Injecting an charged neutronium ingot into an overheated ember metal block to craft transcendium",
"advancements.anvilcraft.transcendence.title": "Transcendence",
"advancements.anvilcraft.vanilla_iron_plate.description": "Smash iron ingots on the stamping platform to obtain heavy weighted pressure plate",
"advancements.anvilcraft.vanilla_iron_plate.title": "Vanilla iron plate",
@@ -307,8 +307,8 @@
"block.anvilcraft.ember_metal_block": "Block of Ember Metal",
"block.anvilcraft.ember_smithing_table": "Ember Smithing Table",
"block.anvilcraft.end_dust": "End Dust",
- "block.anvilcraft.exp_cauldron": "Exp Cauldron",
"block.anvilcraft.exp_fluid": "Exp Fluid",
+ "block.anvilcraft.exp_fluid_cauldron": "Exp Fluid Cauldron",
"block.anvilcraft.exp_gem_block": "Block of Experience Gem",
"block.anvilcraft.exposed_copper_pressure_plate": "Exposed Copper Pressure Plate",
"block.anvilcraft.ferrite_core_magnet_block": "Ferrite-Cored Block of Magnet",
@@ -992,11 +992,12 @@
"screen.anvilcraft.integration_screen.category.interaction": "Interaction",
"screen.anvilcraft.integration_screen.category.modify": "Modify",
"screen.anvilcraft.integration_screen.category.recipe_query": "Recipe Query",
- "screen.anvilcraft.integration_screen.extra": "Extra Mod:",
+ "screen.anvilcraft.integration_screen.extra": "Extra Download:",
"screen.anvilcraft.integration_screen.loaded": "Loaded",
"screen.anvilcraft.integration_screen.not_found": "Not Installed",
"screen.anvilcraft.integration_screen.not_loaded": "Recommended",
- "screen.anvilcraft.integration_screen.target": "Target Mod:",
+ "screen.anvilcraft.integration_screen.note": "To access the manual, first choose and download a third-party manual mod, then download the compatibility add-on for it from this mod. A total of %d additional mods are required. Download links have been provided and can be accessed by clicking the button.",
+ "screen.anvilcraft.integration_screen.target": "Main Mod Download:",
"screen.anvilcraft.integration_screen.title": "Integrations",
"screen.anvilcraft.integration_screen.url.curseforge": "CurseForge",
"screen.anvilcraft.integration_screen.url.github": "Github Repository",
diff --git a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/ice_maker.json b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/ice_maker.json
index 5ee99eef6c..5812a3999a 100644
--- a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/ice_maker.json
+++ b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/ice_maker.json
@@ -3,7 +3,7 @@
"criteria": {
"make_ice": {
"conditions": {
- "id": "anvilcraft:squeezing/power_snow_from_ice"
+ "id": "anvilcraft:squeezing/powder_snow_cauldron_from_snow_block"
},
"trigger": "anvilcraft:in_world_recipe"
}
diff --git a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/noble_metal.json b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/noble_metal.json
index cae0c49b35..451290863d 100644
--- a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/noble_metal.json
+++ b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/noble_metal.json
@@ -1,11 +1,35 @@
{
"parent": "anvilcraft:anvilcraft/industrial_grade_smelting",
"criteria": {
- "royal_metal": {
+ "has_royal_steel_block": {
"conditions": {
- "id": "anvilcraft:super_heating/royal_steel_ingot"
+ "items": [
+ {
+ "items": "anvilcraft:royal_steel_block"
+ }
+ ]
},
- "trigger": "anvilcraft:in_world_recipe"
+ "trigger": "minecraft:inventory_changed"
+ },
+ "has_royal_steel_ingot": {
+ "conditions": {
+ "items": [
+ {
+ "items": "anvilcraft:royal_steel_ingot"
+ }
+ ]
+ },
+ "trigger": "minecraft:inventory_changed"
+ },
+ "has_royal_steel_nugget": {
+ "conditions": {
+ "items": [
+ {
+ "items": "anvilcraft:royal_steel_nugget"
+ }
+ ]
+ },
+ "trigger": "minecraft:inventory_changed"
}
},
"display": {
@@ -22,7 +46,9 @@
},
"requirements": [
[
- "royal_metal"
+ "has_royal_steel_block",
+ "has_royal_steel_ingot",
+ "has_royal_steel_nugget"
]
],
"sends_telemetry_event": true
diff --git a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/transcendence.json b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/transcendence.json
index 84c0c881be..9c641627e8 100644
--- a/src/generated/resources/data/anvilcraft/advancement/anvilcraft/transcendence.json
+++ b/src/generated/resources/data/anvilcraft/advancement/anvilcraft/transcendence.json
@@ -1,11 +1,35 @@
{
"parent": "anvilcraft:anvilcraft/overheated",
"criteria": {
- "transcendium_block": {
+ "has_transcendium_block": {
"conditions": {
- "id": "anvilcraft:item_inject/transcendium_block"
+ "items": [
+ {
+ "items": "anvilcraft:transcendium_block"
+ }
+ ]
},
- "trigger": "anvilcraft:in_world_recipe"
+ "trigger": "minecraft:inventory_changed"
+ },
+ "has_transcendium_ingot": {
+ "conditions": {
+ "items": [
+ {
+ "items": "anvilcraft:transcendium_ingot"
+ }
+ ]
+ },
+ "trigger": "minecraft:inventory_changed"
+ },
+ "has_transcendium_nugget": {
+ "conditions": {
+ "items": [
+ {
+ "items": "anvilcraft:transcendium_nugget"
+ }
+ ]
+ },
+ "trigger": "minecraft:inventory_changed"
}
},
"display": {
@@ -23,7 +47,9 @@
},
"requirements": [
[
- "transcendium_block"
+ "has_transcendium_block",
+ "has_transcendium_ingot",
+ "has_transcendium_nugget"
]
],
"sends_telemetry_event": true
diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_cauldron.json b/src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_fluid_cauldron.json
similarity index 72%
rename from src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_cauldron.json
rename to src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_fluid_cauldron.json
index 3d51ed2fe4..447dece802 100644
--- a/src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_cauldron.json
+++ b/src/generated/resources/data/anvilcraft/advancement/recipes/bulging/exp_fluid_cauldron.json
@@ -3,7 +3,7 @@
"criteria": {
"has_the_recipe": {
"conditions": {
- "recipe": "anvilcraft:bulging/exp_cauldron"
+ "recipe": "anvilcraft:bulging/exp_fluid_cauldron"
},
"trigger": "minecraft:recipe_unlocked"
}
@@ -15,7 +15,7 @@
],
"rewards": {
"recipes": [
- "anvilcraft:bulging/exp_cauldron"
+ "anvilcraft:bulging/exp_fluid_cauldron"
]
}
}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk.json b/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk.json
new file mode 100644
index 0000000000..1c2eeacc2c
--- /dev/null
+++ b/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk.json
@@ -0,0 +1,21 @@
+{
+ "parent": "minecraft:recipes/root",
+ "criteria": {
+ "has_the_recipe": {
+ "conditions": {
+ "recipe": "anvilcraft:squeezing/exp_fluid_from_sculk"
+ },
+ "trigger": "minecraft:recipe_unlocked"
+ }
+ },
+ "requirements": [
+ [
+ "has_the_recipe"
+ ]
+ ],
+ "rewards": {
+ "recipes": [
+ "anvilcraft:squeezing/exp_fluid_from_sculk"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk_use_frost_anvil.json b/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk_use_frost_anvil.json
new file mode 100644
index 0000000000..a7d5ddcceb
--- /dev/null
+++ b/src/generated/resources/data/anvilcraft/advancement/recipes/squeezing/exp_fluid_from_sculk_use_frost_anvil.json
@@ -0,0 +1,21 @@
+{
+ "parent": "minecraft:recipes/root",
+ "criteria": {
+ "has_the_recipe": {
+ "conditions": {
+ "recipe": "anvilcraft:squeezing/exp_fluid_from_sculk_use_frost_anvil"
+ },
+ "trigger": "minecraft:recipe_unlocked"
+ }
+ },
+ "requirements": [
+ [
+ "has_the_recipe"
+ ]
+ ],
+ "rewards": {
+ "recipes": [
+ "anvilcraft:squeezing/exp_fluid_from_sculk_use_frost_anvil"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/exp_cauldron.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/exp_fluid_cauldron.json
similarity index 84%
rename from src/generated/resources/data/anvilcraft/loot_table/blocks/exp_cauldron.json
rename to src/generated/resources/data/anvilcraft/loot_table/blocks/exp_fluid_cauldron.json
index b02998cb1d..850fb105b1 100644
--- a/src/generated/resources/data/anvilcraft/loot_table/blocks/exp_cauldron.json
+++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/exp_fluid_cauldron.json
@@ -17,5 +17,5 @@
"rolls": 1.0
}
],
- "random_sequence": "anvilcraft:blocks/exp_cauldron"
+ "random_sequence": "anvilcraft:blocks/exp_fluid_cauldron"
}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/recipe/bulging/exp_cauldron.json b/src/generated/resources/data/anvilcraft/recipe/bulging/exp_fluid_cauldron.json
similarity index 80%
rename from src/generated/resources/data/anvilcraft/recipe/bulging/exp_cauldron.json
rename to src/generated/resources/data/anvilcraft/recipe/bulging/exp_fluid_cauldron.json
index 64b2b71f86..4688557880 100644
--- a/src/generated/resources/data/anvilcraft/recipe/bulging/exp_cauldron.json
+++ b/src/generated/resources/data/anvilcraft/recipe/bulging/exp_fluid_cauldron.json
@@ -7,5 +7,5 @@
}
],
"results": [],
- "transform": "anvilcraft:exp"
+ "transform": "anvilcraft:exp_fluid"
}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk.json b/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk.json
new file mode 100644
index 0000000000..b5820437c2
--- /dev/null
+++ b/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk.json
@@ -0,0 +1,18 @@
+{
+ "type": "anvilcraft:squeezing",
+ "anvil": {
+ "anvil": {
+ "blocks": "anvilcraft:frost_anvil"
+ },
+ "inverted": true
+ },
+ "chance": 0.1,
+ "consume": -250,
+ "ingredient": {
+ "blocks": "minecraft:sculk"
+ },
+ "result": {
+ "block": "minecraft:air"
+ },
+ "transform": "anvilcraft:exp_fluid"
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk_use_frost_anvil.json b/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk_use_frost_anvil.json
new file mode 100644
index 0000000000..282a28713e
--- /dev/null
+++ b/src/generated/resources/data/anvilcraft/recipe/squeezing/exp_fluid_from_sculk_use_frost_anvil.json
@@ -0,0 +1,17 @@
+{
+ "type": "anvilcraft:squeezing",
+ "anvil": {
+ "anvil": {
+ "blocks": "anvilcraft:frost_anvil"
+ }
+ },
+ "chance": 0.4,
+ "consume": -250,
+ "ingredient": {
+ "blocks": "minecraft:sculk"
+ },
+ "result": {
+ "block": "minecraft:air"
+ },
+ "transform": "anvilcraft:exp_fluid"
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/anvilcraft/tags/block/heatable_blocks.json b/src/generated/resources/data/anvilcraft/tags/block/heatable_blocks.json
index 28860baefe..7b4f485e3c 100644
--- a/src/generated/resources/data/anvilcraft/tags/block/heatable_blocks.json
+++ b/src/generated/resources/data/anvilcraft/tags/block/heatable_blocks.json
@@ -11,6 +11,7 @@
"anvilcraft:incandescent_netherite_block",
"anvilcraft:incandescent_tungsten_block",
"anvilcraft:overheated_ember_metal_block",
+ "#c:storage_blocks/tungsten",
"minecraft:netherite_block"
]
}
\ No newline at end of file
diff --git a/src/generated/resources/data/minecraft/tags/block/cauldrons.json b/src/generated/resources/data/minecraft/tags/block/cauldrons.json
index 82d13a849d..5ea64d09c3 100644
--- a/src/generated/resources/data/minecraft/tags/block/cauldrons.json
+++ b/src/generated/resources/data/minecraft/tags/block/cauldrons.json
@@ -4,7 +4,7 @@
"anvilcraft:melt_gem_cauldron",
"anvilcraft:honey_cauldron",
"anvilcraft:obsidian_cauldron",
- "anvilcraft:exp_cauldron",
+ "anvilcraft:exp_fluid_cauldron",
"anvilcraft:oil_cauldron",
"anvilcraft:fire_cauldron",
"anvilcraft:white_cement_cauldron",
diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json
index 3c1e0d18b2..b8b45428ad 100644
--- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json
+++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json
@@ -216,7 +216,7 @@
"anvilcraft:melt_gem_cauldron",
"anvilcraft:honey_cauldron",
"anvilcraft:obsidian_cauldron",
- "anvilcraft:exp_cauldron",
+ "anvilcraft:exp_fluid_cauldron",
"anvilcraft:oil_cauldron",
"anvilcraft:fire_cauldron",
"anvilcraft:white_cement_cauldron",
diff --git a/src/main/java/dev/dubhe/anvilcraft/anvil/TranscendiumBehavior.java b/src/main/java/dev/dubhe/anvilcraft/anvil/TranscendiumBehavior.java
index 9b484fd8fa..cc5ec916fe 100644
--- a/src/main/java/dev/dubhe/anvilcraft/anvil/TranscendiumBehavior.java
+++ b/src/main/java/dev/dubhe/anvilcraft/anvil/TranscendiumBehavior.java
@@ -4,6 +4,7 @@
import dev.dubhe.anvilcraft.api.event.AnvilEvent;
import dev.dubhe.anvilcraft.init.block.ModBlocks;
import dev.dubhe.anvilcraft.init.item.ModItems;
+import dev.dubhe.anvilcraft.util.TriggerUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.util.RandomSource;
diff --git a/src/main/java/dev/dubhe/anvilcraft/api/SpawningManager.java b/src/main/java/dev/dubhe/anvilcraft/api/SpawningManager.java
index e25b50ffe3..299452559f 100644
--- a/src/main/java/dev/dubhe/anvilcraft/api/SpawningManager.java
+++ b/src/main/java/dev/dubhe/anvilcraft/api/SpawningManager.java
@@ -3,6 +3,7 @@
import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.block.InductionLightBlock;
import dev.dubhe.anvilcraft.block.entity.InductionLightBlockEntity;
+import dev.dubhe.anvilcraft.util.Util;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
import net.minecraft.core.BlockPos;
@@ -12,6 +13,7 @@
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.phys.Vec3;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.entity.living.MobSpawnEvent;
@@ -76,13 +78,13 @@ private SpawningManager(Level level) {
* 添加电感灯方块到对应的生物生成控制集合中
*
*
- * 根据 isAnimal 参数决定将指定位置的诱导灯添加到动物生成控制集合或非动物生物生成控制集合。
+ * 根据 isAnimal 参数决定将指定位置的电感灯添加到动物生成控制集合或非动物生物生成控制集合。
* 该方法会获取对应世界的 SpawningManager 实例,并将方块位置添加到相应的集合中。
*
*
- * @param pos 诱导灯方块的位置
+ * @param pos 电感灯方块的位置
* @param level 方块所在的世界
- * @param isAnimal true表示该诱导灯用于控制动物生成,false表示用于控制非动物生物生成
+ * @param isAnimal true表示该电感灯用于控制动物生成,false表示用于控制非动物生物生成
* @see SpawningManager#getInstance(Level)
* @see #animalLightBlockSet
* @see #nonAnimalLightBlockSet
@@ -100,51 +102,55 @@ public static void addLightBlock(BlockPos pos, Level level, boolean isAnimal) {
* 检查并阻止特定类型的生物在电感灯方块的生效区域内生成
*
*
- * 遍历指定的诱导灯方块位置集合,检查每个方块是否仍有效并且处于点亮状态。
- * 如果生物位于某个有效诱导灯方块的阻挡区域内,则根据生物类型和诱导灯设置阻止其生成。
- * 同时清理已失效的诱导灯方块位置。
+ * 遍历指定的电感灯方块位置集合,检查每个方块是否仍有效并且处于点亮状态。
+ * 如果生物位于某个有效电感灯方块的阻挡区域内,则根据生物类型和电感灯设置阻止其生成。
+ * 同时清理已失效的电感灯方块位置。
*
*
* @param level 生物生成所在的世界
* @param event 生物生成位置检查事件
- * @param lightPosSet 诱导灯方块位置集合
+ * @param lightPosSet 电感灯方块位置集合
* @param isAnimal true表示检查动物生成,false表示检查非动物生物生成
+ * @return 是否成功阻止生成实体
* @see InductionLightBlock#isLit(BlockState)
* @see InductionLightBlock#canBlockMobSummoning(BlockState)
* @see InductionLightBlock#canBlockAnimalSummoning(BlockState)
- * @see InductionLightBlockEntity#blockingArea
+ * @see InductionLightBlockEntity#isInRange(Vec3)
* @see MobSpawnEvent.PositionCheck#setResult(MobSpawnEvent.PositionCheck.Result)
*/
- private static void ignoreSummonMob(Level level, MobSpawnEvent.PositionCheck event, Set lightPosSet, boolean isAnimal) {
+ private static boolean ignoreSummonMob(Level level, MobSpawnEvent.PositionCheck event, Set lightPosSet, boolean isAnimal) {
Mob entity = event.getEntity();
Iterator iterator = lightPosSet.iterator();
while (iterator.hasNext()) {
BlockPos lightPos = iterator.next();
+ if (!level.isLoaded(lightPos)) continue;
BlockState state = level.getBlockState(lightPos);
- if (
- state.getBlock() instanceof InductionLightBlock
- && InductionLightBlock.isLit(state)
- && (InductionLightBlock.canBlockMobSummoning(state)
- || InductionLightBlock.canBlockAnimalSummoning(state))
- ) {
- if (
- level.getBlockEntity(lightPos) instanceof InductionLightBlockEntity blockEntity
- && blockEntity.blockingArea.get().contains(entity.position())
- ) {
- if (isAnimal) {
- if (entity instanceof Animal) {
- event.setResult(MobSpawnEvent.PositionCheck.Result.FAIL);
- }
- } else {
- if (!(entity instanceof Animal)) {
- event.setResult(MobSpawnEvent.PositionCheck.Result.FAIL);
- }
- }
- }
- } else {
+
+ // 电感灯是否开启
+ if (!(state.getBlock() instanceof InductionLightBlock) || InductionLightBlock.isLit(state)) {
+ iterator.remove();
+ continue;
+ }
+
+ // 电感灯模式是否正确
+ if (isAnimal ? InductionLightBlock.canBlockAnimalSummoning(state) : InductionLightBlock.canBlockMobSummoning(state)) {
iterator.remove();
+ continue;
}
+
+ // 实体是否位于该电感灯影响范围内
+ boolean isInRange = Util.castSafely(level.getBlockEntity(lightPos), InductionLightBlockEntity.class)
+ .map(be -> be.isInRange(entity.position()))
+ .orElse(false);
+ if (!isInRange) continue;
+
+ // 电感灯模式与实体类型是否匹配
+ if (isAnimal != entity instanceof Animal) continue;
+
+ event.setResult(MobSpawnEvent.PositionCheck.Result.FAIL);
+ return true;
}
+ return false;
}
/**
@@ -175,7 +181,8 @@ private static void blockEntitySummon(MobSpawnEvent.PositionCheck event) {
Level level = entity.level();
SpawningManager spawningManager = getInstance(level);
- ignoreSummonMob(level, event, spawningManager.animalLightBlockSet, true);
- ignoreSummonMob(level, event, spawningManager.nonAnimalLightBlockSet, false);
+ if (!ignoreSummonMob(level, event, spawningManager.animalLightBlockSet, true)) {
+ ignoreSummonMob(level, event, spawningManager.nonAnimalLightBlockSet, false);
+ }
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/api/advancement/AdvancementLineHelper.java b/src/main/java/dev/dubhe/anvilcraft/api/advancement/AdvancementLineHelper.java
index e577c031f5..42e765a2b1 100644
--- a/src/main/java/dev/dubhe/anvilcraft/api/advancement/AdvancementLineHelper.java
+++ b/src/main/java/dev/dubhe/anvilcraft/api/advancement/AdvancementLineHelper.java
@@ -38,6 +38,7 @@
import net.minecraft.advancements.critereon.PlayerTrigger;
import net.minecraft.advancements.critereon.RecipeCraftedTrigger;
import net.minecraft.advancements.critereon.SlotsPredicate;
+import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
@@ -171,6 +172,16 @@ public AdvancementHelper hasItems(String key, ItemLike... items) {
return this.addCriterion(key, InventoryChangeTrigger.TriggerInstance.hasItems(items));
}
+ public AdvancementHelper hasItemAny(String keyPrefix, ItemLike... items) {
+ for (ItemLike item : items) {
+ this.addCriterion(
+ keyPrefix + BuiltInRegistries.ITEM.getKey(item.asItem()).getPath(),
+ InventoryChangeTrigger.TriggerInstance.hasItems(item)
+ );
+ }
+ return this;
+ }
+
public AdvancementHelper useItem(String key, ItemLike item) {
return this.addCriterion(key, UseItemTrigger.TriggerInstance.useItem(item.asItem()));
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/api/sliding/SlidingBlockSection.java b/src/main/java/dev/dubhe/anvilcraft/api/sliding/SlidingBlockSection.java
index bd2a881517..eb205671fb 100644
--- a/src/main/java/dev/dubhe/anvilcraft/api/sliding/SlidingBlockSection.java
+++ b/src/main/java/dev/dubhe/anvilcraft/api/sliding/SlidingBlockSection.java
@@ -132,7 +132,8 @@ public void setBlock(Level level, BlockPos center, Entity entity) {
Block.dropResources(state, level, pos);
continue;
}
- if (level.getFluidState(pos).getType() == Fluids.WATER) {
+ if (level.getFluidState(pos).getType() == Fluids.WATER
+ && state.hasProperty(BlockStateProperties.WATERLOGGED)) {
state = state.setValue(BlockStateProperties.WATERLOGGED, true);
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/impl/AffectRangeProviderImpl.java b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/impl/AffectRangeProviderImpl.java
index 146a300206..df85c90092 100644
--- a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/impl/AffectRangeProviderImpl.java
+++ b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/impl/AffectRangeProviderImpl.java
@@ -3,6 +3,7 @@
import dev.dubhe.anvilcraft.api.tooltip.providers.IAffectRangeProvider;
import dev.dubhe.anvilcraft.api.tooltip.providers.IHasAffectRange;
import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
@@ -14,8 +15,9 @@ public boolean accepts(BlockEntity entity) {
@Override
public VoxelShape affectRange(BlockEntity entity) {
- if (entity instanceof IHasAffectRange) {
- return Shapes.create(((IHasAffectRange) entity).shape());
+ // 有作用范围且作用范围不为 null
+ if (entity instanceof IHasAffectRange har && har.shape() instanceof AABB shape) {
+ return Shapes.create(shape);
}
return null;
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/providers/IHasAffectRange.java b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/providers/IHasAffectRange.java
index 5a1191b21c..d71a2512d8 100644
--- a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/providers/IHasAffectRange.java
+++ b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/providers/IHasAffectRange.java
@@ -2,9 +2,12 @@
import net.minecraft.world.phys.AABB;
+import javax.annotation.Nullable;
+
/**
* 拥有作用范围的方块实体
*/
public interface IHasAffectRange {
+ @Nullable
AABB shape();
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/MineralFountainBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/MineralFountainBlock.java
index b5a7ff005f..64b3058998 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/MineralFountainBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/MineralFountainBlock.java
@@ -3,6 +3,7 @@
import com.mojang.serialization.MapCodec;
import dev.dubhe.anvilcraft.block.entity.MineralFountainBlockEntity;
import dev.dubhe.anvilcraft.init.block.ModBlockEntities;
+import dev.dubhe.anvilcraft.util.TriggerUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
@@ -50,6 +51,7 @@ public RenderShape getRenderShape(BlockState state) {
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
setTickCount(level, pos);
+ if (!oldState.is(state.getBlock())) TriggerUtil.mineralFountainCreate(level, pos);
super.onPlace(state, level, pos, oldState, movedByPiston);
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java
index 2e8e1f7425..98d5d6da53 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java
@@ -166,6 +166,6 @@ public void applyDiskData(CompoundTag data) {
@Override
public AABB shape() {
- return range;
+ return this.range;
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/InductionLightBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/InductionLightBlockEntity.java
index 1dfd588580..736a946904 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/entity/InductionLightBlockEntity.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/InductionLightBlockEntity.java
@@ -1,13 +1,14 @@
package dev.dubhe.anvilcraft.block.entity;
+import dev.dubhe.anvilcraft.AnvilCraft;
import dev.dubhe.anvilcraft.api.RipeningManager;
import dev.dubhe.anvilcraft.api.SpawningManager;
import dev.dubhe.anvilcraft.api.power.IPowerConsumer;
import dev.dubhe.anvilcraft.api.power.PowerGrid;
+import dev.dubhe.anvilcraft.api.tooltip.providers.IHasAffectRange;
import dev.dubhe.anvilcraft.block.InductionLightBlock;
-import dev.dubhe.anvilcraft.block.state.LightColor;
import dev.dubhe.anvilcraft.util.AabbUtil;
-import dev.dubhe.anvilcraft.util.Lazy;
+import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.core.BlockPos;
@@ -16,14 +17,17 @@
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
+import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
@Setter
@Getter
-public class InductionLightBlockEntity extends BlockEntity implements IPowerConsumer {
- public final Lazy blockingArea = new Lazy<>(() -> AabbUtil.centerSectionTo3x3x3(this.getBlockPos()));
+public class InductionLightBlockEntity extends BlockEntity implements IPowerConsumer, IHasAffectRange {
+ @Getter(AccessLevel.NONE)
+ private int ripeningRangeCache = AnvilCraft.CONFIG.inductionLightBlockRipeningRange;
+ private AABB ripeningArea;
+ private AABB blockingArea;
private PowerGrid grid;
- private int rangeSize = 5;
public InductionLightBlockEntity(BlockEntityType> type, BlockPos pos, BlockState blockState) {
super(type, pos, blockState);
@@ -37,35 +41,30 @@ public static InductionLightBlockEntity createBlockEntity(
return new InductionLightBlockEntity(type, pos, blockState);
}
- public void tick(Level level1) {
- flushState(level1, getBlockPos());
- LightColor color = getBlockState().getValue(InductionLightBlock.COLOR);
- if (color == LightColor.PINK && InductionLightBlock.isLit(this.getBlockState())) {
- RipeningManager.from(level1).doRipen(getBlockPos());
- } else if (color == LightColor.YELLOW) {
- if (level != null) {
- SpawningManager.addLightBlock(getBlockPos(), level, false);
- }
- } else if (color == LightColor.DARK) {
- if (level != null) {
- SpawningManager.addLightBlock(getBlockPos(), level, true);
- }
+ public void tick(Level level) {
+ this.flushState(level, this.getBlockPos());
+ if (InductionLightBlock.canCropGrow(this.getBlockState()) && InductionLightBlock.isLit(this.getBlockState())) {
+ RipeningManager.from(level).doRipen(this.getBlockPos());
+ } else if (InductionLightBlock.canBlockMobSummoning(this.getBlockState())) {
+ SpawningManager.addLightBlock(this.getBlockPos(), level, false);
+ } else if (InductionLightBlock.canBlockAnimalSummoning(this.getBlockState())) {
+ SpawningManager.addLightBlock(this.getBlockPos(), level, true);
}
}
@Override
public int getInputPower() {
- if (level == null) return 1;
- return getBlockState().getValue(InductionLightBlock.POWERED)
+ if (this.level == null) return 1;
+ return this.getBlockState().getValue(InductionLightBlock.POWERED)
? 0
- : getBlockState().getValue(InductionLightBlock.COLOR).dissipation;
+ : this.getBlockState().getValue(InductionLightBlock.COLOR).dissipation;
}
@Override
@Nullable
public Level getCurrentLevel() {
- if (level != null) {
- return level;
+ if (this.level != null) {
+ return this.level;
} else {
return null;
}
@@ -73,6 +72,39 @@ public Level getCurrentLevel() {
@Override
public BlockPos getPos() {
- return getBlockPos();
+ return this.getBlockPos();
+ }
+
+ @Override
+ public @Nullable AABB shape() {
+ return switch (this.getBlockState().getValue(InductionLightBlock.COLOR)) {
+ case PRIMARY -> null;
+ case PINK -> this.getRipeningArea();
+ case YELLOW, DARK -> this.getBlockingArea();
+ };
+ }
+
+ public AABB getRipeningArea() {
+ if (this.ripeningRangeCache != AnvilCraft.CONFIG.inductionLightBlockRipeningRange) {
+ this.ripeningRangeCache = AnvilCraft.CONFIG.inductionLightBlockRipeningRange;
+ }
+ if (this.ripeningArea == null) {
+ this.ripeningArea = AABB.ofSize(
+ this.getPos().getCenter(),
+ this.ripeningRangeCache,
+ this.ripeningRangeCache,
+ this.ripeningRangeCache
+ );
+ }
+ return this.ripeningArea;
+ }
+
+ public AABB getBlockingArea() {
+ if (this.blockingArea == null) this.blockingArea = AabbUtil.centerSectionTo3x3x3(this.getBlockPos());
+ return this.blockingArea;
+ }
+
+ public boolean isInRange(Vec3 pos) {
+ return this.getBlockingArea().contains(pos);
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/MineralFountainBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/MineralFountainBlockEntity.java
index 6bbb80d1f4..8e0cbe811a 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/entity/MineralFountainBlockEntity.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/MineralFountainBlockEntity.java
@@ -6,6 +6,7 @@
import dev.dubhe.anvilcraft.init.block.ModBlocks;
import dev.dubhe.anvilcraft.init.recipe.ModRecipeTypes;
import dev.dubhe.anvilcraft.recipe.mineral.MineralFountainRecipe;
+import dev.dubhe.anvilcraft.util.TriggerUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
@@ -31,7 +32,8 @@ private MineralFountainBlockEntity(BlockEntityType> type, BlockPos pos, BlockS
}
public static MineralFountainBlockEntity createBlockEntity(
- BlockEntityType> type, BlockPos pos, BlockState blockState) {
+ BlockEntityType> type, BlockPos pos, BlockState blockState
+ ) {
return new MineralFountainBlockEntity(type, pos, blockState);
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/block/sliding/ActivatorSlidingRailBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/sliding/ActivatorSlidingRailBlock.java
index b80f1266a5..b7f835ba58 100644
--- a/src/main/java/dev/dubhe/anvilcraft/block/sliding/ActivatorSlidingRailBlock.java
+++ b/src/main/java/dev/dubhe/anvilcraft/block/sliding/ActivatorSlidingRailBlock.java
@@ -42,6 +42,8 @@
public class ActivatorSlidingRailBlock extends BaseSlidingRailBlock implements IHammerChangeable, IMoveableEntityBlock {
public static final List SIGNAL_SOURCE_SIDES = List.of(
Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
+ public static final List UPDATE_SIDES = List.of(
+ Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
public static final VoxelShape AABB_X = Stream.of(
Block.box(0, 0, 0, 16, 6, 16),
Block.box(0, 6, 11, 16, 16, 16),
@@ -146,6 +148,7 @@ protected void updatePower(Level level, BlockPos pos, BlockState state, BlockPos
boolean shouldPower = this.isPowered(level, pos);
if (powered != shouldPower) {
level.setBlockAndUpdate(pos, state.setValue(POWERED, shouldPower));
+ this.updateAbove(level, pos);
}
if (powered) {
Direction.Axis axis = state.getValue(FACING).getAxis();
@@ -294,10 +297,11 @@ private void updateAbove(Level level, BlockPos pos) {
aboveState.onNeighborChange(level, abovePos, pos);
level.neighborChanged(aboveState, abovePos, this, pos, false);
if (!aboveState.isRedstoneConductor(level, abovePos)) return;
- abovePos = abovePos.above();
- aboveState = level.getBlockState(abovePos);
- if (!aboveState.getWeakChanges(level, abovePos)) return;
- level.neighborChanged(aboveState, abovePos, this, pos, false);
+ for (Direction dir : UPDATE_SIDES) {
+ BlockPos neighborPos = abovePos.relative(dir);
+ BlockState neighborState = level.getBlockState(neighborPos);
+ level.neighborChanged(neighborState, neighborPos, aboveState.getBlock(), abovePos, false);
+ }
}
@Override
diff --git a/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/IntegrationScreen.java b/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/IntegrationScreen.java
index 575843b7c5..4680a146d1 100644
--- a/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/IntegrationScreen.java
+++ b/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/IntegrationScreen.java
@@ -30,14 +30,17 @@
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.FormattedCharSequence;
+import javax.annotation.Nullable;
import java.net.URI;
import java.util.List;
-import javax.annotation.Nullable;
public class IntegrationScreen extends Screen {
public static final Component TITLE = Component.translatable(
"screen.anvilcraft.integration_screen.title"
);
+ public static final Component NOTE = Component.translatable(
+ "screen.anvilcraft.integration_screen.note", 2
+ );
public static final Component CATEGORY_GUIDE = Component.translatable(
"screen.anvilcraft.integration_screen.category.guide"
);
@@ -267,6 +270,59 @@ public void renderToolTip() {
}
}
+ public class NoteIntegrationEntry extends AbstractIntegrationEntry {
+ final Component note;
+
+ static final float SCALE = 0.9f;
+
+ public NoteIntegrationEntry(Component note) {
+ super(null);
+ this.note = note;
+ }
+
+ @Override
+ public void render(
+ GuiGraphics guiGraphics,
+ int index,
+ int top,
+ int left,
+ int width,
+ int height,
+ int mouseX,
+ int mouseY,
+ boolean hovering,
+ float partialTick
+ ) {
+ PoseStack pose = guiGraphics.pose();
+ pose.pushPose();
+ pose.translate(left, top, 0);
+ pose.scale(SCALE, SCALE, 1.0f);
+ int maxWidth = (int) (width / SCALE);
+ guiGraphics.drawWordWrap(Minecraft.getInstance().font, this.note, 0, 0, maxWidth, -1);
+ pose.popPose();
+ }
+
+ @Override
+ public List extends GuiEventListener> children() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public List extends NarratableEntry> narratables() {
+ return ImmutableList.of(new NarratableEntry() {
+ @Override
+ public NarrationPriority narrationPriority() {
+ return NarrationPriority.FOCUSED;
+ }
+
+ @Override
+ public void updateNarration(NarrationElementOutput output) {
+ output.add(NarratedElementType.HINT, NoteIntegrationEntry.this.note);
+ }
+ });
+ }
+ }
+
public class CategoryIntegrationEntry extends AbstractIntegrationEntry {
final Component label;
@@ -352,6 +408,7 @@ public IntegrationList() {
);
IntegrationUtil.Root root = IntegrationUtil.load();
IntegrationUtil.Integrations integrations = root.integration();
+ this.addEntry(new NoteIntegrationEntry(IntegrationScreen.NOTE));
this.addEntry(new CategoryIntegrationEntry(IntegrationScreen.CATEGORY_GUIDE));
integrations.guide().forEach(integration -> this.addEntry(new IntegrationEntry(integration)));
this.addEntry(new CategoryIntegrationEntry(IntegrationScreen.CATEGORY_RECIPE_QUERY));
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/lang/AdvancementLang.java b/src/main/java/dev/dubhe/anvilcraft/data/lang/AdvancementLang.java
index 0208716887..ecae67a853 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/lang/AdvancementLang.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/lang/AdvancementLang.java
@@ -105,7 +105,7 @@ public static void init(RegistrateLangProvider provider) {
provider.add("advancements.anvilcraft.rip_van_winkle.title", "Rip Van Winkle");
provider.add("advancements.anvilcraft.rip_van_winkle.description", "Perform any time warp operation");
- provider.add("advancements.anvilcraft.frost_metal.title", "Rome was not built in a day");
+ provider.add("advancements.anvilcraft.frost_metal.title", "River was not frozen in one day's cold");
provider.add("advancements.anvilcraft.frost_metal.description", "Obtain any frost metal");
provider.add("advancements.anvilcraft.tai_shang_wang_qing.title", "Immortals beyond emotions");
@@ -136,7 +136,7 @@ public static void init(RegistrateLangProvider provider) {
provider.add("advancements.anvilcraft.overheated.description", "Using anvil collision to make ember metal block overheated");
provider.add("advancements.anvilcraft.transcendence.title", "Transcendence");
- provider.add("advancements.anvilcraft.transcendence.description", "Injecting an charged neutronium ingot into an overheated ember metal block to craft transcendium block");
+ provider.add("advancements.anvilcraft.transcendence.description", "Injecting an charged neutronium ingot into an overheated ember metal block to craft transcendium");
provider.add("advancements.anvilcraft.nuclear_power_10a.title", "Nuclear power, piece of cake!");
provider.add("advancements.anvilcraft.nuclear_power_10a.description", "Using heat collector to collect overheated blocks' heat");
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/lang/IntegrationScreenLang.java b/src/main/java/dev/dubhe/anvilcraft/data/lang/IntegrationScreenLang.java
index 835eb78a8b..2bb2059042 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/lang/IntegrationScreenLang.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/lang/IntegrationScreenLang.java
@@ -5,6 +5,14 @@
public class IntegrationScreenLang {
public static void init(RegistrateLangProvider provider) {
provider.add("screen.anvilcraft.integration_screen.title", "Integrations");
+ provider.add(
+ "screen.anvilcraft.integration_screen.note",
+ "To access the manual, "
+ + "first choose and download a third-party manual mod, "
+ + "then download the compatibility add-on for it from this mod. "
+ + "A total of %d additional mods are required. "
+ + "Download links have been provided and can be accessed by clicking the button."
+ );
provider.add("screen.anvilcraft.integration_screen.category.guide", "Guide");
provider.add("screen.anvilcraft.integration_screen.category.recipe_query", "Recipe Query");
provider.add("screen.anvilcraft.integration_screen.category.info_hud", "Info HUD");
@@ -12,8 +20,8 @@ public static void init(RegistrateLangProvider provider) {
provider.add("screen.anvilcraft.integration_screen.category.interaction", "Interaction");
provider.add("screen.anvilcraft.integration_screen.category.compatible", "Compatible");
provider.add("screen.anvilcraft.integration_screen.category.additional", "Additional");
- provider.add("screen.anvilcraft.integration_screen.target", "Target Mod:");
- provider.add("screen.anvilcraft.integration_screen.extra", "Extra Mod:");
+ provider.add("screen.anvilcraft.integration_screen.target", "Main Mod Download:");
+ provider.add("screen.anvilcraft.integration_screen.extra", "Extra Download:");
provider.add("screen.anvilcraft.integration_screen.loaded", "Loaded");
provider.add("screen.anvilcraft.integration_screen.not_loaded", "Recommended");
provider.add("screen.anvilcraft.integration_screen.not_found", "Not Installed");
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/BulgingRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/BulgingRecipeLoader.java
index 3a2a888484..7a3bb59762 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/BulgingRecipeLoader.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/BulgingRecipeLoader.java
@@ -69,9 +69,9 @@ public static void init(RegistrateRecipeProvider provider) {
.save(provider);
BulgingRecipe.builder()
.cauldron(Blocks.WATER_CAULDRON)
- .transform(ModBlocks.EXP_CAULDRON.get())
+ .transform(ModBlocks.EXP_FLUID_CAULDRON.get())
.requires(ModItems.EXP_GEM)
- .save(provider, AnvilCraft.of("bulging/exp_cauldron"));
+ .save(provider, AnvilCraft.of("bulging/exp_fluid_cauldron"));
}
private static void bulging(RegistrateRecipeProvider provider, ItemLike input, ItemLike result, int consume) {
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/ItemInjectRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/ItemInjectRecipeLoader.java
index b85537050a..3c6071a9c4 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/ItemInjectRecipeLoader.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/ItemInjectRecipeLoader.java
@@ -1,7 +1,11 @@
package dev.dubhe.anvilcraft.data.recipe;
import com.tterrag.registrate.providers.RegistrateRecipeProvider;
+import dev.anvilcraft.lib.recipe.component.ItemIngredientPredicate;
import dev.dubhe.anvilcraft.init.block.ModBlocks;
+import dev.dubhe.anvilcraft.init.item.ModItemSubPredicates;
+import dev.dubhe.anvilcraft.init.item.ModItems;
+import dev.dubhe.anvilcraft.item.property.predicate.ItemEnchantmentCountPredicate;
import dev.dubhe.anvilcraft.recipe.anvil.wrap.ItemInjectRecipe;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/SqueezingRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/SqueezingRecipeLoader.java
index 6f318ab9f0..3167368dbd 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/SqueezingRecipeLoader.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/SqueezingRecipeLoader.java
@@ -15,6 +15,24 @@ public static void init(RegistrateRecipeProvider provider) {
squeezing(provider, Blocks.MOSS_BLOCK, Blocks.MOSS_CARPET, Blocks.WATER_CAULDRON, 333);
squeezing(provider, Blocks.MAGMA_BLOCK, Blocks.NETHERRACK, ModBlocks.LAVA_CAULDRON.get(), 250);
squeezing(provider, Blocks.SNOW_BLOCK, Blocks.ICE, Blocks.POWDER_SNOW_CAULDRON, 333);
+
+ SqueezingRecipe.builder()
+ .requires(Blocks.SCULK)
+ .result(Blocks.AIR)
+ .transform(ModBlocks.EXP_FLUID_CAULDRON.get())
+ .produce(250)
+ .chance(0.1f)
+ .noFrostAnvil()
+ .save(provider, AnvilCraft.of("squeezing/exp_fluid_from_sculk"));
+
+ SqueezingRecipe.builder()
+ .requires(Blocks.SCULK)
+ .result(Blocks.AIR)
+ .transform(ModBlocks.EXP_FLUID_CAULDRON.get())
+ .produce(250)
+ .chance(0.4f)
+ .frostAnvil()
+ .save(provider, AnvilCraft.of("squeezing/exp_fluid_from_sculk_use_frost_anvil"));
}
public static void squeezing(RegistrateRecipeProvider provider, Block requires, Block result, Block cauldron, int produce) {
@@ -23,7 +41,6 @@ public static void squeezing(RegistrateRecipeProvider provider, Block requires,
.result(result)
.transform(cauldron)
.produce(produce)
- .save(
- provider, AnvilCraft.of("squeezing/%s_from_%s".formatted(getName(cauldron), getName(requires))));
+ .save(provider, AnvilCraft.of("squeezing/%s_from_%s".formatted(getName(cauldron), getName(requires))));
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/data/tags/BlockTagLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/tags/BlockTagLoader.java
index 6698e4fffe..f0e72c5cd9 100644
--- a/src/main/java/dev/dubhe/anvilcraft/data/tags/BlockTagLoader.java
+++ b/src/main/java/dev/dubhe/anvilcraft/data/tags/BlockTagLoader.java
@@ -276,6 +276,7 @@ public static void init(RegistrateTagsProvider provider) {
.add(findResourceKey(Blocks.COPPER_GRATE));
provider.addTag(ModBlockTags.HEATABLE_BLOCKS)
+ .addTag(ModBlockTags.STORAGE_BLOCKS_TUNGSTEN)
.add(findResourceKey(Blocks.NETHERITE_BLOCK));
provider.addTag(ModBlockTags.STICKABLE_WITH_SLIDING_RAILS)
diff --git a/src/main/java/dev/dubhe/anvilcraft/init/ModAdvancements.java b/src/main/java/dev/dubhe/anvilcraft/init/ModAdvancements.java
index b24ab5c35b..1dceee89c3 100644
--- a/src/main/java/dev/dubhe/anvilcraft/init/ModAdvancements.java
+++ b/src/main/java/dev/dubhe/anvilcraft/init/ModAdvancements.java
@@ -290,7 +290,7 @@ public class ModAdvancements {
true,
false
)
- .inWorldRecipeAnc("make_ice", "squeezing/power_snow_from_ice")
+ .inWorldRecipeAnc("make_ice", "squeezing/powder_snow_cauldron_from_snow_block")
.build("ice_maker");
_4_TO_81 = iceLine.next()
.display(
@@ -502,7 +502,8 @@ public class ModAdvancements {
true,
false
)
- .inWorldRecipeAnc("royal_metal", "super_heating/royal_steel_ingot")
+ .requireAny()
+ .hasItemAny("has_", ModBlocks.ROYAL_STEEL_BLOCK, ModItems.ROYAL_STEEL_INGOT, ModItems.ROYAL_STEEL_NUGGET)
.build("noble_metal");
OVERSEER = mainLine.createBranch().next()
@@ -607,9 +608,7 @@ public class ModAdvancements {
false
)
.requireAny()
- .hasItems("has_frost_metal_block", ModBlocks.FROST_METAL_BLOCK)
- .hasItems("has_frost_metal_ingot", ModItems.FROST_METAL_INGOT)
- .hasItems("has_frost_metal_nugget", ModItems.FROST_METAL_NUGGET)
+ .hasItemAny("has_", ModBlocks.FROST_METAL_BLOCK, ModItems.FROST_METAL_INGOT, ModItems.FROST_METAL_NUGGET)
.build("frost_metal");
TAI_SHANG_WANG_QING = frostLine.next()
.display(
@@ -884,7 +883,8 @@ public class ModAdvancements {
true,
false
)
- .inWorldRecipeAnc("transcendium_block", "item_inject/transcendium_block")
+ .requireAny()
+ .hasItemAny("has_", ModBlocks.TRANSCENDIUM_BLOCK, ModItems.TRANSCENDIUM_INGOT, ModItems.TRANSCENDIUM_NUGGET)
.build("transcendence");
}
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java
index 74afe6d940..803ffd10a5 100644
--- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java
+++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java
@@ -4035,7 +4035,8 @@ public class ModBlocks {
.onRegister(block -> Item.BY_BLOCK.put(block, Items.CAULDRON))
.register();
- public static final BlockEntry EXP_CAULDRON = REGISTRATE.block("exp_cauldron", ExpFluidCauldronBlock::new)
+ public static final BlockEntry EXP_FLUID_CAULDRON = REGISTRATE
+ .block("exp_fluid_cauldron", ExpFluidCauldronBlock::new)
.initialProperties(() -> Blocks.CAULDRON)
.blockstate(DataGenUtil::noExtraModelOrState)
.loot((tables, block) -> tables.dropOther(block, Items.CAULDRON))
diff --git a/src/main/java/dev/dubhe/anvilcraft/init/item/ModItemSubPredicates.java b/src/main/java/dev/dubhe/anvilcraft/init/item/ModItemSubPredicates.java
index 87596ecb09..19f4d277ee 100644
--- a/src/main/java/dev/dubhe/anvilcraft/init/item/ModItemSubPredicates.java
+++ b/src/main/java/dev/dubhe/anvilcraft/init/item/ModItemSubPredicates.java
@@ -2,6 +2,7 @@
import com.mojang.serialization.Codec;
import dev.dubhe.anvilcraft.AnvilCraft;
+import dev.dubhe.anvilcraft.item.property.predicate.ItemEnchantmentCountPredicate;
import dev.dubhe.anvilcraft.item.property.predicate.ItemSavedEntityPredicate;
import net.minecraft.advancements.critereon.ItemSubPredicate;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -20,6 +21,12 @@ public class ModItemSubPredicates {
ItemSavedEntityPredicate.CODEC
);
+ public static final DeferredHolder, ItemSubPredicate.Type> ENCHANTMENT_COUNT =
+ register(
+ "enchantment_count",
+ ItemEnchantmentCountPredicate.CODEC.codec()
+ );
+
public static DeferredHolder, ItemSubPredicate.Type> register(
String name,
Codec codec
diff --git a/src/main/java/dev/dubhe/anvilcraft/init/recipe/ModRecipePredicateTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/recipe/ModRecipePredicateTypes.java
index bc8cca1927..5c7be88432 100644
--- a/src/main/java/dev/dubhe/anvilcraft/init/recipe/ModRecipePredicateTypes.java
+++ b/src/main/java/dev/dubhe/anvilcraft/init/recipe/ModRecipePredicateTypes.java
@@ -3,6 +3,7 @@
import dev.anvilcraft.lib.recipe.init.LibRegistries;
import dev.anvilcraft.lib.recipe.predicate.IRecipePredicate;
import dev.dubhe.anvilcraft.AnvilCraft;
+import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasAnvil;
import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasCauldron;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
@@ -15,4 +16,9 @@ public class ModRecipePredicateTypes {
"has_cauldron",
HasCauldron.Type::new
);
+
+ public static final DeferredHolder, HasAnvil.Type> HAS_ANVIL = PREDICATE_TYPE.register(
+ "has_anvil",
+ HasAnvil.Type::new
+ );
}
diff --git a/src/main/java/dev/dubhe/anvilcraft/item/property/predicate/ItemEnchantmentCountPredicate.java b/src/main/java/dev/dubhe/anvilcraft/item/property/predicate/ItemEnchantmentCountPredicate.java
new file mode 100644
index 0000000000..65b971bbb6
--- /dev/null
+++ b/src/main/java/dev/dubhe/anvilcraft/item/property/predicate/ItemEnchantmentCountPredicate.java
@@ -0,0 +1,40 @@
+package dev.dubhe.anvilcraft.item.property.predicate;
+
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.MapCodec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.advancements.critereon.ItemSubPredicate;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.network.codec.ByteBufCodecs;
+import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.enchantment.ItemEnchantments;
+
+public record ItemEnchantmentCountPredicate(int min, int max) implements ItemSubPredicate {
+ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
+ Codec.INT
+ .fieldOf("min")
+ .forGetter(ItemEnchantmentCountPredicate::min),
+ Codec.INT
+ .fieldOf("max")
+ .forGetter(ItemEnchantmentCountPredicate::max)
+ ).apply(inst, ItemEnchantmentCountPredicate::new));
+ public static final StreamCodec STREAM_CODEC = StreamCodec.composite(
+ ByteBufCodecs.VAR_INT,
+ ItemEnchantmentCountPredicate::min,
+ ByteBufCodecs.VAR_INT,
+ ItemEnchantmentCountPredicate::max,
+ ItemEnchantmentCountPredicate::new
+ );
+
+ public static ItemEnchantmentCountPredicate count(int count) {
+ return new ItemEnchantmentCountPredicate(count, count);
+ }
+
+ @Override
+ public boolean matches(ItemStack stack) {
+ int size = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).size();
+ return size >= this.min && size <= this.max;
+ }
+}
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/builder/ExtendInWorldRecipeBuilder.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/builder/ExtendInWorldRecipeBuilder.java
index 9d0c4c9f9f..c7461ac15b 100644
--- a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/builder/ExtendInWorldRecipeBuilder.java
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/builder/ExtendInWorldRecipeBuilder.java
@@ -1,10 +1,12 @@
package dev.dubhe.anvilcraft.recipe.anvil.builder;
import dev.anvilcraft.lib.recipe.builder.InWorldRecipeBuilder;
+import dev.anvilcraft.lib.recipe.component.BlockStatePredicate;
import dev.anvilcraft.lib.recipe.outcome.SpawnItem;
import dev.anvilcraft.lib.recipe.trigger.IRecipeTrigger;
import dev.dubhe.anvilcraft.recipe.anvil.outcome.DamageAnvil;
import dev.dubhe.anvilcraft.recipe.anvil.outcome.ProduceHeat;
+import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasAnvil;
import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasCauldron;
import lombok.EqualsAndHashCode;
import net.minecraft.resources.ResourceLocation;
@@ -259,6 +261,27 @@ public ExtendInWorldRecipeBuilder hasCauldron(double x, double y, double z, Bloc
return this.with(HasCauldron.builder().cauldron(cauldron).offset(new Vec3(x, y, z)).consume(consume).build());
}
+ /**
+ * 添加铁砧谓词
+ *
+ * @param consumer BlockStatePredicate构建器消费者
+ * @return 当前构建器实例
+ */
+ public ExtendInWorldRecipeBuilder hasAnvil(Consumer consumer) {
+ BlockStatePredicate.Builder builder = BlockStatePredicate.builder();
+ consumer.accept(builder);
+ return this.with(new HasAnvil(builder));
+ }
+
+ /**
+ * 添加浮霜铁砧谓词
+ *
+ * @return 当前构建器实例
+ */
+ public ExtendInWorldRecipeBuilder hasFrostAnvil() {
+ return this.with(HasAnvil.frostOnly());
+ }
+
/**
* 添加生成物品结果
*
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasAnvil.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasAnvil.java
new file mode 100644
index 0000000000..e94e262390
--- /dev/null
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasAnvil.java
@@ -0,0 +1,83 @@
+package dev.dubhe.anvilcraft.recipe.anvil.predicate.block;
+
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.MapCodec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+import dev.anvilcraft.lib.recipe.component.BlockStatePredicate;
+import dev.anvilcraft.lib.recipe.predicate.IRecipePredicate;
+import dev.anvilcraft.lib.recipe.util.InWorldRecipeContext;
+import dev.dubhe.anvilcraft.init.block.ModBlocks;
+import dev.dubhe.anvilcraft.init.recipe.ModRecipePredicateTypes;
+import net.minecraft.network.RegistryFriendlyByteBuf;
+import net.minecraft.network.codec.ByteBufCodecs;
+import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.tags.BlockTags;
+import net.minecraft.world.entity.item.FallingBlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+
+/**
+ * 铁砧条件谓词
+ *
+ * 用于检查铁砧是否符合条件
+ *
+ * @param anvil 铁砧方块条件谓词
+ */
+public record HasAnvil(BlockStatePredicate anvil, boolean inverted) implements IRecipePredicate {
+ public static final HasAnvil DEFAULT = new HasAnvil(BlockStatePredicate.builder().of(BlockTags.ANVIL).build(), false);
+ public static final HasAnvil DEFAULT_INVERTED = new HasAnvil(HasAnvil.DEFAULT.anvil, true);
+ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
+ BlockStatePredicate.CODEC
+ .optionalFieldOf("anvil", HasAnvil.DEFAULT.anvil)
+ .forGetter(HasAnvil::anvil),
+ Codec.BOOL
+ .optionalFieldOf("inverted", false)
+ .forGetter(HasAnvil::inverted)
+ ).apply(inst, HasAnvil::new));
+ public static final StreamCodec STREAM_CODEC = StreamCodec.composite(
+ BlockStatePredicate.STREAM_CODEC,
+ HasAnvil::anvil,
+ ByteBufCodecs.BOOL,
+ HasAnvil::inverted,
+ HasAnvil::new
+ );
+
+ public HasAnvil(BlockStatePredicate.Builder anvil, boolean inverted) {
+ this(anvil.build(), inverted);
+ }
+
+ public HasAnvil(BlockStatePredicate.Builder anvil) {
+ this(anvil.build(), false);
+ }
+
+ public static HasAnvil frostOnly() {
+ return new HasAnvil(BlockStatePredicate.builder().of(ModBlocks.FROST_ANVIL));
+ }
+
+ public static HasAnvil noFrost() {
+ return new HasAnvil(BlockStatePredicate.builder().of(ModBlocks.FROST_ANVIL), true);
+ }
+
+ @Override
+ public Type getType() {
+ return ModRecipePredicateTypes.HAS_ANVIL.get();
+ }
+
+ @Override
+ public boolean test(InWorldRecipeContext ctx) {
+ if (!(ctx.getEntity() instanceof FallingBlockEntity falling)) return this.inverted;
+ if (!this.anvil.test(ctx.getLevel(), falling.getBlockState(), null)) return this.inverted;
+ return !this.inverted;
+ }
+
+ public static class Type implements IRecipePredicate.Type {
+ @Override
+ public MapCodec codec() {
+ return HasAnvil.CODEC;
+ }
+
+ @Override
+ public StreamCodec streamCodec() {
+ return HasAnvil.STREAM_CODEC;
+ }
+ }
+}
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasCauldron.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasCauldron.java
index 1b90cd1878..c44777bfcd 100644
--- a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasCauldron.java
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/block/HasCauldron.java
@@ -35,9 +35,15 @@
* @param fluid 流体ID
* @param consume 消耗量(负数表示产生)
* @param transform 转换后的流体ID
+ * @param chance 转换成功的概率
*/
-public record HasCauldron(Vec3 offset, ResourceLocation fluid, int consume, ResourceLocation transform)
- implements IRecipePredicate {
+public record HasCauldron(
+ Vec3 offset,
+ ResourceLocation fluid,
+ int consume,
+ ResourceLocation transform,
+ float chance
+) implements IRecipePredicate {
/**
* 空炼药锅标识
*/
@@ -55,6 +61,7 @@ public record HasCauldron(Vec3 offset, ResourceLocation fluid, int consume, Reso
* @param fluid 流体ID
* @param consume 消耗量
* @param transform 转换后的流体ID
+ * @param chance 转换成功的概率
*/
public HasCauldron {
}
@@ -66,41 +73,71 @@ public record HasCauldron(Vec3 offset, ResourceLocation fluid, int consume, Reso
* @return HasCauldron实例
*/
public static HasCauldron empty(Vec3 offset) {
- return new HasCauldron(offset, EMPTY, 0, NULL);
+ return new HasCauldron(offset, EMPTY, 0, NULL, 1.0f);
}
@Override
+ @SuppressWarnings("RedundantIfStatement")
public boolean test(InWorldRecipeContext context) {
+ /*
+ * 由于过去在此出现了非常多的bug,在此罗列,以供测试:
+ * 1. 时移不完成宝石转化
+ * 2. 无水执行不消耗水的物品膨发
+ * 3. 流体不足执行配方
+ * 4. 流体不满1B不执行配方
+ * 4. 压榨重置炼药锅——永远无法达到满锅的真实
+ * 5. 一桶原油完成多份余烬金属的合成
+ * 6. 锅满了,仍可以熔融宝石,溢出浪费
+ * 7. 流体可以相互替代使用
+ */
Vec3 pos = context.getPos().add(this.offset());
BlockPos blockPos = BlockPos.containing(pos);
BlockCache cache = context.computeIfAbsent(BlockCache.BLOCK_CACHE);
BlockState curState = cache.getBlockState(blockPos);
if (!curState.is(BlockTags.CAULDRONS)) return false;
+
+ // 需要消耗液体
if (this.consume > 0) {
+ // 不是对应的流体锅 否决
+ if (!curState.is(this.getFluidCauldron())) return false;
Optional> optionalCur = HasCauldron.getFluidLevel(curState);
if (optionalCur.isPresent()) {
+ // 该流体锅可分层,需要更多判断
+ // 流体不足 否决
Tuple fluidLevel = optionalCur.get();
int currentLevel = fluidLevel.getB();
- int maxLevel = fluidLevel.getA().max;
- return currentLevel >= maxLevel;
+ IntegerProperty maxLevel = fluidLevel.getA();
+ if (HasCauldron.layer2Mb(maxLevel, currentLevel) < this.consume) return false;
+ // 如果要产生流体,而之前的流体不被消耗完 否决
+ if (HasCauldron.isNotEmpty(this.transform()) && HasCauldron.layer2Mb(maxLevel, currentLevel) > this.consume) return false;
+ // 因为产生了不同的流体,因此不用进行剩余容量是否存在的判断
+ }
+ // 不消耗流体
+ } else {
+ // 有液体要求且不是对应的流体锅 否决
+ if (HasCauldron.isNotEmpty(this.fluid()) && !curState.is(this.getFluidCauldron())) return false;
+
+ if (HasCauldron.isNotEmpty(this.transform())) {
+ // 异种液体 否决
+ Block targetCauldron = this.getTransformCauldron();
+ if (!curState.is(Blocks.CAULDRON) && !curState.is(targetCauldron)) return false;
+ // 没有剩余容量 否决
+ if (curState.is(targetCauldron)) {
+ BlockState targetState = targetCauldron.defaultBlockState();
+ Optional> optionalTarget = HasCauldron.getFluidLevel(targetState);
+ int max = optionalTarget.map(tuple -> tuple.getA().max).orElse(0);
+ Optional> optionalCur = HasCauldron.getFluidLevel(curState);
+ int cur = optionalCur.map(Tuple::getB).orElse(0);
+ if (cur >= max) return false;
+ }
}
}
- Block fluidCauldron = this.getFluidCauldron();
- if (curState.is(fluidCauldron)) return true;
- if (HasCauldron.isNotEmpty(this.fluid())) return false;
- if (!HasCauldron.isNotEmpty(this.transform())) return false;
- Block targetCauldron = this.getTransformCauldron();
- if (!curState.is(Blocks.CAULDRON) && !curState.is(targetCauldron)) return false;
- BlockState targetState = targetCauldron.defaultBlockState();
- Optional> optionalTarget = HasCauldron.getFluidLevel(targetState);
- int max = optionalTarget.map(tuple -> tuple.getA().max).orElse(0);
- Optional> optionalCur = HasCauldron.getFluidLevel(curState);
- int cur = optionalCur.map(Tuple::getB).orElse(0);
- return cur < max;
+ return true;
}
@Override
public void accept(InWorldRecipeContext context) {
+ if (context.getLevel().random.nextFloat() > this.chance) return;
if (this.fluid.equals(EMPTY) && !HasCauldron.isNotEmpty(this.transform())) return;
BlockPos blockPos = BlockPos.containing(context.getPos().add(this.offset()));
BlockCache cache = context.computeIfAbsent(BlockCache.BLOCK_CACHE);
@@ -219,10 +256,21 @@ public static class Type implements IRecipePredicate.Type {
* 编解码器
*/
public final MapCodec codec = RecordCodecBuilder.mapCodec(instance -> instance.group(
- Vec3.CODEC.fieldOf("offset").forGetter(HasCauldron::offset),
- ResourceLocation.CODEC.optionalFieldOf("fluid", EMPTY).forGetter(HasCauldron::fluid),
- Codec.INT.optionalFieldOf("consume", 0).forGetter(HasCauldron::consume),
- ResourceLocation.CODEC.optionalFieldOf("transform", NULL).forGetter(HasCauldron::transform)
+ Vec3.CODEC
+ .fieldOf("offset")
+ .forGetter(HasCauldron::offset),
+ ResourceLocation.CODEC
+ .optionalFieldOf("fluid", EMPTY)
+ .forGetter(HasCauldron::fluid),
+ Codec.INT
+ .optionalFieldOf("consume", 0)
+ .forGetter(HasCauldron::consume),
+ ResourceLocation.CODEC
+ .optionalFieldOf("transform", NULL)
+ .forGetter(HasCauldron::transform),
+ Codec.FLOAT
+ .optionalFieldOf("chance", 1.0f)
+ .forGetter(HasCauldron::chance)
).apply(instance, HasCauldron::new)
);
@@ -238,6 +286,8 @@ public static class Type implements IRecipePredicate.Type {
HasCauldron::consume,
ResourceLocation.STREAM_CODEC,
HasCauldron::transform,
+ ByteBufCodecs.FLOAT,
+ HasCauldron::chance,
HasCauldron::new
);
@@ -260,6 +310,7 @@ public static class Builder {
private ResourceLocation fluid = HasCauldron.EMPTY;
private int consume = 0;
private ResourceLocation transform = HasCauldron.NULL;
+ private float chance = 1;
/**
* 设置偏移量
@@ -387,13 +438,24 @@ public Builder produce(int produce) {
return this;
}
+ /**
+ * 设置转换成功的概率
+ *
+ * @param chance 概率
+ * @return 构建器实例
+ */
+ public Builder chance(float chance) {
+ this.chance = chance;
+ return this;
+ }
+
/**
* 构建HasCauldron实例
*
* @return HasCauldron实例
*/
public HasCauldron build() {
- return new HasCauldron(this.offset, this.fluid, this.consume, this.transform);
+ return new HasCauldron(this.offset, this.fluid, this.consume, this.transform, this.chance);
}
}
}
\ No newline at end of file
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/AbstractProcessRecipe.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/AbstractProcessRecipe.java
index 31132ad274..f4d04f68e2 100644
--- a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/AbstractProcessRecipe.java
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/AbstractProcessRecipe.java
@@ -14,6 +14,7 @@
import dev.dubhe.anvilcraft.init.recipe.ModRecipeTriggers;
import dev.dubhe.anvilcraft.recipe.anvil.builder.AbstractRecipeBuilder;
import dev.dubhe.anvilcraft.recipe.anvil.outcome.ProduceHeat;
+import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasAnvil;
import dev.dubhe.anvilcraft.recipe.component.HasCauldronSimple;
import lombok.Getter;
import net.minecraft.core.Vec3i;
@@ -144,6 +145,15 @@ public HasCauldronSimple getHasCauldron() {
return this.property.getHasCauldron();
}
+ /**
+ * 获取铁砧条件
+ *
+ * @return 炼药锅条件
+ */
+ public HasAnvil getHasAnvil() {
+ return this.property.getHasAnvil();
+ }
+
/**
* 获取产热信息
*
@@ -489,6 +499,11 @@ public static class Property {
*/
private HasCauldronSimple hasCauldron = null;
+ /**
+ * 铁砧条件
+ */
+ private HasAnvil hasAnvil = HasAnvil.DEFAULT;
+
/**
* 产热信息
*/
@@ -687,6 +702,17 @@ public Property setHasCauldron(HasCauldronSimple hasCauldron) {
return this;
}
+ /**
+ * 设置铁砧条件
+ *
+ * @param hasAnvil 铁砧条件
+ * @return 属性实例
+ */
+ public Property setHasAnvil(HasAnvil hasAnvil) {
+ this.hasAnvil = hasAnvil;
+ return this;
+ }
+
/**
* 设置产热信息
*
@@ -738,7 +764,8 @@ private int getPriority() {
+ (this.resultItems == null ? 0 : this.resultItems.size())
+ (this.inputBlocks == null ? 0 : this.inputBlocks.size() * 100)
+ (this.resultBlocks == null ? 0 : this.resultBlocks.size())
- + (this.hasCauldron != null ? 1 : 0);
+ + (this.hasCauldron != null ? 1 : 0)
+ + (this.hasAnvil != null ? 1 : 0);
}
/**
@@ -751,6 +778,9 @@ private List> getNonConflictingPredicates() {
if (this.hasCauldron != null) {
predicates.add(this.hasCauldron.toHasCauldron(this.getCauldronOffset()));
}
+ if (!Objects.equals(this.hasAnvil, HasAnvil.DEFAULT)) {
+ predicates.add(this.hasAnvil);
+ }
if (this.inputBlocks != null) {
for (int i = 0; i < this.inputBlocks.size(); i++) {
BlockStatePredicate block = this.inputBlocks.get(i);
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/SqueezingRecipe.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/SqueezingRecipe.java
index df31932185..036d6036a1 100644
--- a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/SqueezingRecipe.java
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/SqueezingRecipe.java
@@ -6,6 +6,7 @@
import dev.anvilcraft.lib.recipe.component.ChanceBlockState;
import dev.dubhe.anvilcraft.init.recipe.ModRecipeTypes;
import dev.dubhe.anvilcraft.recipe.anvil.builder.AbstractRecipeBuilder;
+import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasAnvil;
import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasCauldron;
import dev.dubhe.anvilcraft.recipe.anvil.util.WrapUtils;
import dev.dubhe.anvilcraft.recipe.component.HasCauldronSimple;
@@ -20,6 +21,8 @@
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.Block;
+import java.util.function.Consumer;
+
/**
* 压榨配方类
*
@@ -37,7 +40,8 @@ public class SqueezingRecipe extends AbstractProcessRecipe {
public SqueezingRecipe(
BlockStatePredicate ingredient,
ChanceBlockState result,
- HasCauldronSimple hasCauldron
+ HasCauldronSimple hasCauldron,
+ HasAnvil hasAnvil
) {
super(
new Property()
@@ -46,6 +50,7 @@ public SqueezingRecipe(
.setInputBlocks(ingredient)
.setCauldronOffset(new Vec3i(0, -2, 0))
.setHasCauldron(hasCauldron)
+ .setHasAnvil(hasAnvil)
.setBlockOutputOffset(new Vec3i(0, -1, 0))
.setResultBlocks(result)
);
@@ -96,7 +101,10 @@ public static class Serializer implements RecipeSerializer {
.fieldOf("result")
.forGetter(SqueezingRecipe::getFirstResultBlock),
HasCauldronSimple.CODEC
- .forGetter(SqueezingRecipe::getHasCauldron)
+ .forGetter(SqueezingRecipe::getHasCauldron),
+ HasAnvil.CODEC.codec()
+ .optionalFieldOf("anvil", HasAnvil.DEFAULT)
+ .forGetter(SqueezingRecipe::getHasAnvil)
).apply(instance, SqueezingRecipe::new));
/**
@@ -109,6 +117,8 @@ public static class Serializer implements RecipeSerializer {
SqueezingRecipe::getFirstResultBlock,
HasCauldronSimple.STREAM_CODEC,
SqueezingRecipe::getHasCauldron,
+ HasAnvil.STREAM_CODEC,
+ SqueezingRecipe::getHasAnvil,
SqueezingRecipe::new
);
@@ -142,6 +152,11 @@ public static class Builder extends AbstractRecipeBuilder {
*/
private final HasCauldronSimple.Builder hasCauldron = HasCauldronSimple.empty();
+ /**
+ * 铁砧条件
+ */
+ private HasAnvil hasAnvil = HasAnvil.DEFAULT;
+
/**
* 添加原料方块
*
@@ -273,9 +288,76 @@ public Builder consume(int consume) {
return this;
}
+ /**
+ * 设置转换成功的概率
+ *
+ * @param chance 转换成功的概率
+ * @return 构建器实例
+ */
+ public Builder chance(float chance) {
+ if (chance <= 0) return this;
+ this.hasCauldron.chance(chance);
+ return this;
+ }
+
+ /**
+ * 设置铁砧条件
+ *
+ * @param anvil 铁砧方块
+ * @return 构建器实例
+ */
+ public Builder anvil(Block anvil) {
+ this.hasAnvil = new HasAnvil(BlockStatePredicate.builder().of(anvil));
+ return this;
+ }
+
+ /**
+ * 设置铁砧条件
+ *
+ * @param anvil 铁砧方块标签
+ * @return 构建器实例
+ */
+ public Builder anvil(TagKey anvil) {
+ this.hasAnvil = new HasAnvil(BlockStatePredicate.builder().of(anvil));
+ return this;
+ }
+
+ /**
+ * 设置铁砧条件
+ *
+ * @param consumer 铁砧条件谓词消费者
+ * @return 构建器实例
+ */
+ public Builder anvil(Consumer consumer) {
+ BlockStatePredicate.Builder builder = BlockStatePredicate.builder();
+ consumer.accept(builder);
+ this.hasAnvil = new HasAnvil(builder);
+ return this;
+ }
+
+ /**
+ * 设置浮霜铁砧条件
+ *
+ * @return 构建器实例
+ */
+ public Builder frostAnvil() {
+ this.hasAnvil = HasAnvil.frostOnly();
+ return this;
+ }
+
+ /**
+ * 设置非浮霜铁砧条件
+ *
+ * @return 构建器实例
+ */
+ public Builder noFrostAnvil() {
+ this.hasAnvil = HasAnvil.noFrost();
+ return this;
+ }
+
@Override
public SqueezingRecipe buildRecipe() {
- return new SqueezingRecipe(this.ingredient, this.result, hasCauldron.build());
+ return new SqueezingRecipe(this.ingredient, this.result, hasCauldron.build(), this.hasAnvil);
}
@Override
diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/component/HasCauldronSimple.java b/src/main/java/dev/dubhe/anvilcraft/recipe/component/HasCauldronSimple.java
index 16d1dd65ea..d2bcf189a6 100644
--- a/src/main/java/dev/dubhe/anvilcraft/recipe/component/HasCauldronSimple.java
+++ b/src/main/java/dev/dubhe/anvilcraft/recipe/component/HasCauldronSimple.java
@@ -19,14 +19,16 @@
* @param fluid 流体ID
* @param consume 消耗量(负数表示产生)
* @param transform 转换后的流体ID
+ * @param chance 转换成功的概率
*/
-public record HasCauldronSimple(ResourceLocation fluid, int consume, ResourceLocation transform) {
+public record HasCauldronSimple(ResourceLocation fluid, int consume, ResourceLocation transform, float chance) {
/**
* 构造一个简单的炼药锅条件
*
* @param fluid 流体ID
* @param consume 消耗量
* @param transform 转换后的流体ID
+ * @param chance 转换成功的概率
*/
public HasCauldronSimple {
}
@@ -44,7 +46,10 @@ public record HasCauldronSimple(ResourceLocation fluid, int consume, ResourceLoc
.forGetter(HasCauldronSimple::consume),
ResourceLocation.CODEC
.optionalFieldOf("transform", HasCauldron.NULL)
- .forGetter(HasCauldronSimple::transform)
+ .forGetter(HasCauldronSimple::transform),
+ Codec.FLOAT
+ .optionalFieldOf("chance", 1.0f)
+ .forGetter(HasCauldronSimple::chance)
).apply(instance, HasCauldronSimple::new)
);
@@ -55,7 +60,7 @@ public record HasCauldronSimple(ResourceLocation fluid, int consume, ResourceLoc
* @return HasCauldron谓词
*/
public HasCauldron toHasCauldron(Vec3 offset) {
- return new HasCauldron(offset, fluid, consume, transform);
+ return new HasCauldron(offset, fluid, consume, transform, chance);
}
/**
@@ -86,6 +91,8 @@ public Block getTransformCauldron() {
HasCauldronSimple::consume,
ResourceLocation.STREAM_CODEC,
HasCauldronSimple::transform,
+ ByteBufCodecs.FLOAT,
+ HasCauldronSimple::chance,
HasCauldronSimple::new
);
@@ -115,6 +122,7 @@ public static class Builder {
private ResourceLocation fluid = HasCauldron.EMPTY;
private int consume = 0;
private ResourceLocation transform = HasCauldron.NULL;
+ private float chance = 1f;
/**
* 创建一个空的构建器
@@ -170,13 +178,24 @@ public Builder consume(int consume) {
return this;
}
+ /**
+ * 设置转换成功的概率
+ *
+ * @param chance 转换成功的概率
+ * @return 构建器实例
+ */
+ public Builder chance(float chance) {
+ this.chance = chance;
+ return this;
+ }
+
/**
* 构建HasCauldronSimple实例
*
* @return HasCauldronSimple实例
*/
public HasCauldronSimple build() {
- return new HasCauldronSimple(fluid, consume, transform);
+ return new HasCauldronSimple(fluid, consume, transform, chance);
}
}
}
\ No newline at end of file
diff --git a/src/main/java/dev/dubhe/anvilcraft/util/ModInteractionMap.java b/src/main/java/dev/dubhe/anvilcraft/util/ModInteractionMap.java
index 4db2d00083..bf34605dee 100644
--- a/src/main/java/dev/dubhe/anvilcraft/util/ModInteractionMap.java
+++ b/src/main/java/dev/dubhe/anvilcraft/util/ModInteractionMap.java
@@ -42,7 +42,7 @@ public static void initInteractionMap() {
hand,
stack,
ModItems.EXP_BUCKET.asStack(),
- (s) -> ModBlocks.EXP_CAULDRON.get().isFull(state),
+ (s) -> ModBlocks.EXP_FLUID_CAULDRON.get().isFull(state),
SoundEvents.BUCKET_FILL
)
);
@@ -238,7 +238,7 @@ public static void initInteractionMap() {
player,
hand,
stack,
- ModBlocks.EXP_CAULDRON.get().fullFilled(),
+ ModBlocks.EXP_FLUID_CAULDRON.get().fullFilled(),
SoundEvents.BUCKET_EMPTY
)
);
@@ -250,7 +250,7 @@ public static void initInteractionMap() {
player.awardStat(Stats.USE_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
if (level.random.nextBoolean()) {
- level.setBlockAndUpdate(pos, ModBlocks.EXP_CAULDRON.getDefaultState());
+ level.setBlockAndUpdate(pos, ModBlocks.EXP_FLUID_CAULDRON.getDefaultState());
}
level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS);
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
diff --git a/src/main/java/dev/dubhe/anvilcraft/util/TriggerUtil.java b/src/main/java/dev/dubhe/anvilcraft/util/TriggerUtil.java
index 8a86a25c3f..b00fcdcd1e 100644
--- a/src/main/java/dev/dubhe/anvilcraft/util/TriggerUtil.java
+++ b/src/main/java/dev/dubhe/anvilcraft/util/TriggerUtil.java
@@ -144,4 +144,12 @@ public static void heatCollectorOutput(Level level, BlockPos pos, int output) {
}
}
}
+
+ public static void mineralFountainCreate(Level level, BlockPos pos) {
+ if (!level.isClientSide) {
+ for (ServerPlayer player : PlayerUtil.searchPlayerByPos(level, pos, 7)) {
+ ModCriterionTriggers.MINERAL_FOUNTAIN_CREATE.get().trigger(player);
+ }
+ }
+ }
}
diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml
index 8255630128..d873c90ef6 100644
--- a/src/main/resources/META-INF/neoforge.mods.toml
+++ b/src/main/resources/META-INF/neoforge.mods.toml
@@ -70,6 +70,13 @@ file="META-INF/accesstransformer.cfg"
ordering="NONE"
side="BOTH"
+[[dependencies."${mod_id}"]]
+ modId="anvillib"
+ type="required"
+ versionRange="[1.4.0,)"
+ ordering="AFTER"
+ side="BOTH"
+
[[dependencies."${mod_id}"]]
modId="jei"
type="optional"
diff --git a/src/main/resources/assets/anvilcraft/blockstates/exp_cauldron.json b/src/main/resources/assets/anvilcraft/blockstates/exp_cauldron.json
deleted file mode 100644
index 11846c6f47..0000000000
--- a/src/main/resources/assets/anvilcraft/blockstates/exp_cauldron.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "variants": {
- "level=1": {
- "model": "anvilcraft:block/exp_cauldron_level1"
- },
- "level=2": {
- "model": "anvilcraft:block/exp_cauldron_level2"
- },
- "level=3": {
- "model": "anvilcraft:block/exp_cauldron_level3"
- },
- "level=4": {
- "model": "anvilcraft:block/exp_cauldron_full"
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/resources/assets/anvilcraft/blockstates/exp_fluid_cauldron.json b/src/main/resources/assets/anvilcraft/blockstates/exp_fluid_cauldron.json
new file mode 100644
index 0000000000..a737780bb5
--- /dev/null
+++ b/src/main/resources/assets/anvilcraft/blockstates/exp_fluid_cauldron.json
@@ -0,0 +1,16 @@
+{
+ "variants": {
+ "level=1": {
+ "model": "anvilcraft:block/exp_fluid_cauldron_level1"
+ },
+ "level=2": {
+ "model": "anvilcraft:block/exp_fluid_cauldron_level2"
+ },
+ "level=3": {
+ "model": "anvilcraft:block/exp_fluid_cauldron_level3"
+ },
+ "level=4": {
+ "model": "anvilcraft:block/exp_fluid_cauldron_full"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/anvilcraft/blockstates/experience_cauldron.json b/src/main/resources/assets/anvilcraft/blockstates/experience_cauldron.json
deleted file mode 100644
index 0bb1fb3471..0000000000
--- a/src/main/resources/assets/anvilcraft/blockstates/experience_cauldron.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "variants": {
- "level=1": {
- "model": "anvilcraft:block/experience_cauldron_level1"
- },
- "level=2": {
- "model": "anvilcraft:block/experience_cauldron_level2"
- },
- "level=3": {
- "model": "anvilcraft:block/experience_cauldron_level3"
- },
- "level=4": {
- "model": "anvilcraft:block/experience_cauldron_full"
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/resources/assets/anvilcraft/models/block/exp_cauldron_full.json b/src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_full.json
similarity index 100%
rename from src/main/resources/assets/anvilcraft/models/block/exp_cauldron_full.json
rename to src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_full.json
diff --git a/src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level1.json b/src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level1.json
similarity index 100%
rename from src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level1.json
rename to src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level1.json
diff --git a/src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level2.json b/src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level2.json
similarity index 100%
rename from src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level2.json
rename to src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level2.json
diff --git a/src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level3.json b/src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level3.json
similarity index 100%
rename from src/main/resources/assets/anvilcraft/models/block/exp_cauldron_level3.json
rename to src/main/resources/assets/anvilcraft/models/block/exp_fluid_cauldron_level3.json
diff --git a/src/main/resources/assets/anvilcraft/models/item/ember_metal_heavy_halberd.json b/src/main/resources/assets/anvilcraft/models/item/ember_metal_heavy_halberd.json
index 67562d1eb5..94b22f095b 100644
--- a/src/main/resources/assets/anvilcraft/models/item/ember_metal_heavy_halberd.json
+++ b/src/main/resources/assets/anvilcraft/models/item/ember_metal_heavy_halberd.json
@@ -72,15 +72,6 @@
"up": {"uv": [0, 4, 3, 5], "texture": "#0"}
}
},
- {
- "from": [9.5, 14.5, 8],
- "to": [12.5, 18.5, 8],
- "rotation": {"angle": -45, "axis": "z", "origin": [11, 11, 8]},
- "faces": {
- "north": {"uv": [3, 0, 0, 4], "texture": "#0"},
- "south": {"uv": [0, 0, 3, 4], "texture": "#0"}
- }
- },
{
"from": [10.5, 14.5, 7.5],
"to": [11.5, 16.5, 8.5],
@@ -105,15 +96,6 @@
"up": {"uv": [4, 3, 5, 2], "rotation": 180, "texture": "#0"}
}
},
- {
- "from": [6.7, 9.5, 8],
- "to": [9.7, 17.5, 8],
- "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]},
- "faces": {
- "north": {"uv": [7, 8, 4, 0], "rotation": 180, "texture": "#0"},
- "south": {"uv": [4, 8, 7, 0], "rotation": 180, "texture": "#0"}
- }
- },
{
"from": [7.7, 10.5, 7.5],
"to": [9.7, 13.5, 8.5],
@@ -127,15 +109,6 @@
"down": {"uv": [4, 5, 6, 4], "rotation": 180, "texture": "#0"}
}
},
- {
- "from": [9.5, 6.7, 8],
- "to": [17.5, 9.7, 8],
- "rotation": {"angle": 22.5, "axis": "z", "origin": [11, 11, 8]},
- "faces": {
- "north": {"uv": [7, 0, 4, 8], "rotation": 270, "texture": "#0"},
- "south": {"uv": [4, 0, 7, 8], "rotation": 90, "texture": "#0"}
- }
- },
{
"from": [13.5, 8.7, 7.5],
"to": [15.5, 9.7, 8.5],
@@ -161,6 +134,135 @@
"down": {"uv": [5, 4, 6, 7], "rotation": 90, "texture": "#0"}
}
},
+ {
+ "from": [8.7, 15.5, 7.875],
+ "to": [9.7, 17.5, 8.125],
+ "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [4, 0, 5, 2], "texture": "#0"},
+ "east": {"uv": [4, 0, 5, 2], "texture": "#0"},
+ "south": {"uv": [4, 0, 5, 2], "texture": "#0"},
+ "west": {"uv": [4, 0, 5, 2], "texture": "#0"},
+ "up": {"uv": [4, 0, 5, 1], "texture": "#0"}
+ }
+ },
+ {
+ "from": [7.7, 13.5, 7.875],
+ "to": [8.7, 14.5, 8.125],
+ "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [5, 3, 6, 4], "texture": "#0"},
+ "south": {"uv": [5, 3, 6, 4], "texture": "#0"},
+ "west": {"uv": [5, 3, 6, 4], "texture": "#0"},
+ "up": {"uv": [5, 3, 6, 4], "texture": "#0"}
+ }
+ },
+ {
+ "from": [6.7, 10.5, 7.875],
+ "to": [7.7, 13.5, 8.125],
+ "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [6, 4, 7, 7], "texture": "#0"},
+ "south": {"uv": [6, 4, 7, 7], "texture": "#0"},
+ "west": {"uv": [6, 4, 7, 7], "texture": "#0"},
+ "up": {"uv": [6, 4, 7, 5], "texture": "#0"},
+ "down": {"uv": [6, 6, 7, 7], "texture": "#0"}
+ }
+ },
+ {
+ "from": [7.7, 9.5, 7.875],
+ "to": [9.7, 10.5, 8.125],
+ "rotation": {"angle": -22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [4, 7, 6, 8], "texture": "#0"},
+ "east": {"uv": [4, 7, 5, 8], "texture": "#0"},
+ "south": {"uv": [4, 7, 6, 8], "rotation": 180, "texture": "#0"},
+ "west": {"uv": [5, 7, 6, 8], "texture": "#0"},
+ "up": {"uv": [4, 0, 5, 1], "texture": "#0"},
+ "down": {"uv": [4, 7, 6, 8], "texture": "#0"}
+ }
+ },
+ {
+ "from": [10.5, 16.5, 7.875],
+ "to": [11.5, 18.5, 8.125],
+ "rotation": {"angle": -45, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [2, 0, 1, 2], "texture": "#0"},
+ "east": {"uv": [1, 0, 2, 2], "texture": "#0"},
+ "south": {"uv": [1, 0, 2, 2], "texture": "#0"},
+ "west": {"uv": [1, 0, 2, 2], "texture": "#0"},
+ "up": {"uv": [1, 0, 2, 1], "texture": "#0"}
+ }
+ },
+ {
+ "from": [11.5, 14.5, 7.875],
+ "to": [12.5, 15.5, 8.125],
+ "rotation": {"angle": -45, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [1, 3, 0, 4], "texture": "#0"},
+ "east": {"uv": [0, 3, 1, 4], "texture": "#0"},
+ "south": {"uv": [0, 3, 1, 4], "texture": "#0"},
+ "up": {"uv": [0, 3, 1, 4], "texture": "#0"}
+ }
+ },
+ {
+ "from": [9.5, 14.5, 7.875],
+ "to": [10.5, 15.5, 8.125],
+ "rotation": {"angle": -45, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [3, 3, 2, 4], "texture": "#0"},
+ "south": {"uv": [2, 3, 3, 4], "texture": "#0"},
+ "west": {"uv": [2, 3, 3, 4], "texture": "#0"},
+ "up": {"uv": [2, 3, 3, 4], "texture": "#0"}
+ }
+ },
+ {
+ "from": [15.5, 8.7, 7.875],
+ "to": [17.5, 9.7, 8.125],
+ "rotation": {"angle": 22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [5, 0, 4, 2], "rotation": 270, "texture": "#0"},
+ "east": {"uv": [4, 0, 5, 1], "texture": "#0"},
+ "south": {"uv": [4, 0, 5, 2], "rotation": 90, "texture": "#0"},
+ "up": {"uv": [4, 0, 5, 2], "rotation": 90, "texture": "#0"},
+ "down": {"uv": [4, 0, 5, 2], "rotation": 90, "texture": "#0"}
+ }
+ },
+ {
+ "from": [13.5, 7.7, 7.875],
+ "to": [14.5, 8.7, 8.125],
+ "rotation": {"angle": 22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [6, 3, 5, 4], "rotation": 270, "texture": "#0"},
+ "east": {"uv": [5, 3, 6, 4], "texture": "#0"},
+ "south": {"uv": [5, 3, 6, 4], "rotation": 90, "texture": "#0"},
+ "down": {"uv": [5, 3, 6, 4], "rotation": 90, "texture": "#0"}
+ }
+ },
+ {
+ "from": [10.5, 6.7, 7.875],
+ "to": [13.5, 7.7, 8.125],
+ "rotation": {"angle": 22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [7, 4, 6, 7], "rotation": 270, "texture": "#0"},
+ "east": {"uv": [6, 4, 7, 5], "texture": "#0"},
+ "south": {"uv": [6, 4, 7, 7], "rotation": 90, "texture": "#0"},
+ "west": {"uv": [6, 6, 7, 7], "texture": "#0"},
+ "down": {"uv": [6, 4, 7, 7], "rotation": 90, "texture": "#0"}
+ }
+ },
+ {
+ "from": [9.5, 7.7, 7.875],
+ "to": [10.5, 9.7, 8.125],
+ "rotation": {"angle": 22.5, "axis": "z", "origin": [11, 11, 8]},
+ "faces": {
+ "north": {"uv": [6, 7, 4, 8], "rotation": 270, "texture": "#0"},
+ "south": {"uv": [4, 7, 6, 8], "rotation": 90, "texture": "#0"},
+ "west": {"uv": [4, 7, 6, 8], "rotation": 90, "texture": "#0"},
+ "up": {"uv": [4, 7, 5, 8], "rotation": 90, "texture": "#0"},
+ "down": {"uv": [5, 7, 6, 8], "rotation": 90, "texture": "#0"}
+ }
+ },
{
"from": [6, -4, 6],
"to": [10, -2, 10],
@@ -228,7 +330,7 @@
"scale": [2, 2, 2]
},
"fixed": {
- "rotation": [0, 180, 0],
+ "rotation": [0, -180, 0],
"translation": [0.5, -0.5, 0],
"scale": [0.9, 0.9, 0.9]
}
@@ -244,9 +346,9 @@
"name": "group",
"origin": [11, 11, 8],
"color": 0,
- "children": [5, 6, 7, 8, 9, 10, 11, 12, 13]
+ "children": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
},
- 14,
- 15
+ 22,
+ 23
]
}
\ No newline at end of file