diff --git a/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/src/generated/resources/assets/anvilcraft/lang/en_ud.json index 9f083e793e..53c9f239ad 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -313,7 +313,9 @@ "block.anvilcraft.exposed_copper_pressure_plate": "ǝʇɐןԀ ǝɹnssǝɹԀ ɹǝddoƆ pǝsodxƎ", "block.anvilcraft.ferrite_core_magnet_block": "ʇǝubɐW ɟo ʞɔoןᗺ pǝɹoƆ-ǝʇıɹɹǝℲ", "block.anvilcraft.fire_cauldron": "uoɹpןnɐƆ ǝɹıℲ", + "block.anvilcraft.fish_tank": "ʞuɐ⟘ ɥsıℲ", "block.anvilcraft.flint_block": "ʞɔoןᗺ ʇuıןℲ", + "block.anvilcraft.fluid_tank": "ʞuɐ⟘ pınןℲ", "block.anvilcraft.frost_anvil": "ןıʌuⱯ ʇsoɹℲ", "block.anvilcraft.frost_glass": "ssɐן⅁ ʇsoɹℲ", "block.anvilcraft.frost_grindstone": "ǝuoʇspuıɹ⅁ ʇsoɹℲ", @@ -352,6 +354,7 @@ "block.anvilcraft.item_detector": "ɹoʇɔǝʇǝᗡ ɯǝʇI", "block.anvilcraft.jewelcrafting_table": "ǝןqɐ⟘ buıʇɟɐɹƆ ןǝʍǝſ", "block.anvilcraft.large_cake": "ǝʞɐƆ ǝbɹɐꞀ", + "block.anvilcraft.large_fluid_tank": "ʞuɐ⟘ pınןℲ ǝbɹɐꞀ", "block.anvilcraft.laser_receiver": "ɹǝʌıǝɔǝᴚ ɹǝsɐꞀ", "block.anvilcraft.lava_cauldron": "uoɹpןnɐƆ ɐʌɐꞀ", "block.anvilcraft.lead_block": "pɐǝꞀ ɟo ʞɔoןᗺ", @@ -1238,6 +1241,7 @@ "tooltip.anvilcraft.item.feather_amulet": "ǝbɐɯɐp ןןɐɟ oʇ ʎʇıunɯɯı sʇuɐɹ⅁", "tooltip.anvilcraft.item.ferrite_core_magnet_block": "sǝbɹɐɥɔ ǝʇɐɹǝuǝb oʇ sʞɔoןq ɹǝddoɔ ʇuǝɔɐظpɐ sǝsnɐɔ 'uoʇsıd ǝɥʇ ʎq pǝןןnd puɐ pǝɥsnd uǝɥʍ 'ʍoןǝq ןıʌuɐ ǝɥʇ buıʇɔɐɹʇʇⱯ", "tooltip.anvilcraft.item.filter": "ʇoןs ɹǝʇןıɟ ʎuɐ uı ǝןqɐs∩ ˙sɹǝʇןıɟ ɹo bıɟuoɔ uo pǝsɐq sɯǝʇı sǝɥɔʇɐW", + "tooltip.anvilcraft.item.fish_tank": "˙ɥsıɟ ןɐɔıdoɹʇ ǝɥʇ ǝsɐǝןǝɹ oʇ puɐɥ uı ʇǝʞɔnq ɥsıɟ ןɐɔıdoɹʇ ɐ ɥʇıʍ ʞuɐʇ ɥsıɟ ǝɥʇ ɟo ʇɹɐd ɹǝʍoן ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ\n˙ǝpısuı ɯǝʇı ǝɥʇ ǝɔɐןd oʇ puɐɥ uı ɯǝʇı uɐ ɥʇıʍ doʇ ǝɥʇ ʞɔıןɔ-ʇɥbıᴚ\n˙ʇɔǝɟɟǝ buıɥʇɐǝɹq ɹǝʇɐʍɹǝpun ʎɹɐɹodɯǝʇ ɐ sǝpıʌoɹd pɐǝɥ ɹnoʎ uo ʇı buıɹɐǝM\n˙sısǝɥʇuʎs ןıʌuɐ pǝʇɐןǝɹ ɯɹoɟɹǝd oʇ ʇod ʎɯǝɥɔןɐ ǝɥʇ ɹoɟ ǝʇnʇıʇsqns ɐ sɐ pǝsn ǝq uɐɔ puɐ sʞooן ʇı uɐɥʇ ɹǝıpɹnʇs sı ʇI", "tooltip.anvilcraft.item.frost_anvil": "ɟooɹd ɹǝɥʇıM", "tooltip.anvilcraft.item.frost_grindstone": "ɟooɹd ɹǝɥʇıM", "tooltip.anvilcraft.item.frost_smithing_table": "ɟooɹd ɹǝɥʇıM", diff --git a/src/generated/resources/assets/anvilcraft/lang/en_us.json b/src/generated/resources/assets/anvilcraft/lang/en_us.json index 37047d82b5..828db1a621 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -313,7 +313,9 @@ "block.anvilcraft.exposed_copper_pressure_plate": "Exposed Copper Pressure Plate", "block.anvilcraft.ferrite_core_magnet_block": "Ferrite-Cored Block of Magnet", "block.anvilcraft.fire_cauldron": "Fire Cauldron", + "block.anvilcraft.fish_tank": "Fish Tank", "block.anvilcraft.flint_block": "Flint Block", + "block.anvilcraft.fluid_tank": "Fluid Tank", "block.anvilcraft.frost_anvil": "Frost Anvil", "block.anvilcraft.frost_glass": "Frost Glass", "block.anvilcraft.frost_grindstone": "Frost Grindstone", @@ -352,6 +354,7 @@ "block.anvilcraft.item_detector": "Item Detector", "block.anvilcraft.jewelcrafting_table": "Jewel Crafting Table", "block.anvilcraft.large_cake": "Large Cake", + "block.anvilcraft.large_fluid_tank": "Large Fluid Tank", "block.anvilcraft.laser_receiver": "Laser Receiver", "block.anvilcraft.lava_cauldron": "Lava Cauldron", "block.anvilcraft.lead_block": "Block of Lead", @@ -1238,6 +1241,7 @@ "tooltip.anvilcraft.item.feather_amulet": "Grants immunity to fall damage", "tooltip.anvilcraft.item.ferrite_core_magnet_block": "Attracting the anvil below, when pushed and pulled by the piston, causes adjacent copper blocks to generate charges", "tooltip.anvilcraft.item.filter": "Matches items based on config or filters. Usable in any filter slot", + "tooltip.anvilcraft.item.fish_tank": "It is sturdier than it looks and can be used as a substitute for the alchemy pot to perform related anvil synthesis.\nWearing it on your head provides a temporary underwater breathing effect.\nRight-click the top with an item in hand to place the item inside.\nRight-click the lower part of the fish tank with a tropical fish bucket in hand to release the tropical fish.", "tooltip.anvilcraft.item.frost_anvil": "Wither proof", "tooltip.anvilcraft.item.frost_grindstone": "Wither proof", "tooltip.anvilcraft.item.frost_smithing_table": "Wither proof", diff --git a/src/generated/resources/assets/anvilcraft/models/item/fish_tank.json b/src/generated/resources/assets/anvilcraft/models/item/fish_tank.json new file mode 100644 index 0000000000..6037e38296 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/fish_tank.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/fish_tank" +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/item/fluid_tank.json b/src/generated/resources/assets/anvilcraft/models/item/fluid_tank.json new file mode 100644 index 0000000000..0164d60411 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/fluid_tank.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/fluid_tank" +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/item/large_fluid_tank.json b/src/generated/resources/assets/anvilcraft/models/item/large_fluid_tank.json new file mode 100644 index 0000000000..8b327a33ab --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/large_fluid_tank.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/large_fluid_tank" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fish_tank.json b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fish_tank.json new file mode 100644 index 0000000000..00d23c0710 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fish_tank.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_iron_ingot": { + "conditions": { + "items": [ + { + "items": "minecraft:iron_ingot" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:fish_tank" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_iron_ingot" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:fish_tank" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fluid_tank.json b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fluid_tank.json new file mode 100644 index 0000000000..66fb8f4764 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/misc/fluid_tank.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_fish_tank": { + "conditions": { + "items": [ + { + "items": "anvilcraft:fish_tank" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:fluid_tank" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_fish_tank" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:fluid_tank" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_1.json b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_1.json new file mode 100644 index 0000000000..069370784c --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_1.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:multiblock/large_fluid_tank_1" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:multiblock/large_fluid_tank_1" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_2.json b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_2.json new file mode 100644 index 0000000000..feadc6a2f9 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock/large_fluid_tank_2.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:multiblock/large_fluid_tank_2" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:multiblock/large_fluid_tank_2" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_1.json b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_1.json new file mode 100644 index 0000000000..e32b6c4e10 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_1.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:multiblock_conversion/large_fluid_tank_1" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:multiblock_conversion/large_fluid_tank_1" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_2.json b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_2.json new file mode 100644 index 0000000000..ae462dae60 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/multiblock_conversion/large_fluid_tank_2.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:multiblock_conversion/large_fluid_tank_2" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:multiblock_conversion/large_fluid_tank_2" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/fish_tank.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/fish_tank.json new file mode 100644 index 0000000000..b2adb33019 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/fish_tank.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:fish_tank" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/fish_tank" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/fluid_tank.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/fluid_tank.json new file mode 100644 index 0000000000..719dec20e5 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/fluid_tank.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:fluid_tank" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/fluid_tank" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/large_fluid_tank.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/large_fluid_tank.json new file mode 100644 index 0000000000..a70719bb21 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/large_fluid_tank.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "conditions": [ + { + "block": "anvilcraft:large_fluid_tank", + "condition": "minecraft:block_state_property", + "properties": { + "half": "bottom_center" + } + } + ], + "name": "anvilcraft:large_fluid_tank" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/large_fluid_tank" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/fish_tank.json b/src/generated/resources/data/anvilcraft/recipe/fish_tank.json new file mode 100644 index 0000000000..b34385b016 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/fish_tank.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "minecraft:iron_ingot" + }, + "B": { + "tag": "c:glass_panes" + } + }, + "pattern": [ + "A A", + "B B", + "BBB" + ], + "result": { + "count": 1, + "id": "anvilcraft:fish_tank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/fluid_tank.json b/src/generated/resources/data/anvilcraft/recipe/fluid_tank.json new file mode 100644 index 0000000000..90e2110400 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/fluid_tank.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:plates/brass" + }, + { + "item": "anvilcraft:fish_tank" + } + ], + "result": { + "count": 2, + "id": "anvilcraft:fluid_tank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_1.json b/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_1.json new file mode 100644 index 0000000000..4671e049e3 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_1.json @@ -0,0 +1,31 @@ +{ + "type": "anvilcraft:multiblock", + "pattern": { + "layers": [ + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:fluid_tank" + } + } + }, + "result": { + "count": 1, + "id": "anvilcraft:large_fluid_tank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_2.json b/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_2.json new file mode 100644 index 0000000000..0895607fb7 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/multiblock/large_fluid_tank_2.json @@ -0,0 +1,31 @@ +{ + "type": "anvilcraft:multiblock", + "pattern": { + "layers": [ + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "A A", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:fluid_tank" + } + } + }, + "result": { + "count": 1, + "id": "anvilcraft:large_fluid_tank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_1.json b/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_1.json new file mode 100644 index 0000000000..4cc342bd3c --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_1.json @@ -0,0 +1,210 @@ +{ + "type": "anvilcraft:multiblock_conversion", + "inputPattern": { + "layers": [ + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:fluid_tank" + } + } + }, + "outputPattern": { + "layers": [ + [ + "ABC", + "DEF", + "GHI" + ], + [ + "JKL", + "MNO", + "PQR" + ], + [ + "STU", + "VWX", + "YZ[" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_wn" + } + }, + "B": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_n" + } + }, + "C": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_en" + } + }, + "D": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_w" + } + }, + "E": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_center" + } + }, + "F": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_e" + } + }, + "G": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_ws" + } + }, + "H": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_s" + } + }, + "I": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_es" + } + }, + "J": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_wn" + } + }, + "K": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_n" + } + }, + "L": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_en" + } + }, + "M": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_w" + } + }, + "N": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_center" + } + }, + "O": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_e" + } + }, + "P": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_ws" + } + }, + "Q": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_s" + } + }, + "R": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_es" + } + }, + "S": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_wn" + } + }, + "T": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_n" + } + }, + "U": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_en" + } + }, + "V": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_w" + } + }, + "W": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_center" + } + }, + "X": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_e" + } + }, + "Y": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_ws" + } + }, + "Z": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_s" + } + }, + "[": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_es" + } + } + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_2.json b/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_2.json new file mode 100644 index 0000000000..a02a4f1a9b --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/multiblock_conversion/large_fluid_tank_2.json @@ -0,0 +1,210 @@ +{ + "type": "anvilcraft:multiblock_conversion", + "inputPattern": { + "layers": [ + [ + "AAA", + "AAA", + "AAA" + ], + [ + "AAA", + "A A", + "AAA" + ], + [ + "AAA", + "AAA", + "AAA" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:fluid_tank" + } + } + }, + "outputPattern": { + "layers": [ + [ + "ABC", + "DEF", + "GHI" + ], + [ + "JKL", + "MNO", + "PQR" + ], + [ + "STU", + "VWX", + "YZ[" + ] + ], + "symbols": { + "A": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_wn" + } + }, + "B": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_n" + } + }, + "C": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_en" + } + }, + "D": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_w" + } + }, + "E": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_center" + } + }, + "F": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_e" + } + }, + "G": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_ws" + } + }, + "H": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_s" + } + }, + "I": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "bottom_es" + } + }, + "J": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_wn" + } + }, + "K": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_n" + } + }, + "L": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_en" + } + }, + "M": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_w" + } + }, + "N": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_center" + } + }, + "O": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_e" + } + }, + "P": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_ws" + } + }, + "Q": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_s" + } + }, + "R": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "mid_es" + } + }, + "S": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_wn" + } + }, + "T": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_n" + } + }, + "U": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_en" + } + }, + "V": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_w" + } + }, + "W": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_center" + } + }, + "X": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_e" + } + }, + "Y": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_ws" + } + }, + "Z": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_s" + } + }, + "[": { + "block": "anvilcraft:large_fluid_tank", + "properties": { + "half": "top_es" + } + } + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/tags/fluid/menger_sponge_can_absorb.json b/src/generated/resources/data/anvilcraft/tags/fluid/menger_sponge_can_absorb.json index c96324e575..e277b984ee 100644 --- a/src/generated/resources/data/anvilcraft/tags/fluid/menger_sponge_can_absorb.json +++ b/src/generated/resources/data/anvilcraft/tags/fluid/menger_sponge_can_absorb.json @@ -8,6 +8,7 @@ "anvilcraft:flowing_oil", "anvilcraft:melt_gem", "anvilcraft:flowing_melt_gem", + "anvilcraft:exp_fluid", "#c:cement" ] } \ 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..6c7c95acf2 100644 --- a/src/generated/resources/data/minecraft/tags/block/cauldrons.json +++ b/src/generated/resources/data/minecraft/tags/block/cauldrons.json @@ -1,5 +1,6 @@ { "values": [ + "anvilcraft:fish_tank", "anvilcraft:lava_cauldron", "anvilcraft:melt_gem_cauldron", "anvilcraft:honey_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..c74b7f0c54 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -5,6 +5,8 @@ "anvilcraft:ferrite_core_magnet_block", "anvilcraft:stamping_platform", "anvilcraft:crushing_table", + "anvilcraft:fish_tank", + "anvilcraft:fluid_tank", "anvilcraft:corrupted_beacon", "anvilcraft:giant_anvil", "anvilcraft:spectral_anvil", @@ -56,6 +58,7 @@ "anvilcraft:activator_sliding_rail", "anvilcraft:detector_sliding_rail", "anvilcraft:sliding_rail_stop", + "anvilcraft:large_fluid_tank", "anvilcraft:acceleration_ring", "anvilcraft:deflection_ring", "anvilcraft:void_energy_collector", diff --git a/src/main/java/dev/dubhe/anvilcraft/api/fluid/IFluidHandlerHolder.java b/src/main/java/dev/dubhe/anvilcraft/api/fluid/IFluidHandlerHolder.java new file mode 100644 index 0000000000..ea6b1264e6 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/api/fluid/IFluidHandlerHolder.java @@ -0,0 +1,10 @@ +package dev.dubhe.anvilcraft.api.fluid; + +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +/** + * 持有FluidTank的 + */ +public interface IFluidHandlerHolder { + IFluidHandler getFluidHandler(); +} diff --git a/src/main/java/dev/dubhe/anvilcraft/api/fluid/package-info.java b/src/main/java/dev/dubhe/anvilcraft/api/fluid/package-info.java new file mode 100644 index 0000000000..b994f6ec8b --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/api/fluid/package-info.java @@ -0,0 +1,7 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package dev.dubhe.anvilcraft.api.fluid; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/InfinityFluidTank.java b/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/InfinityFluidTank.java new file mode 100644 index 0000000000..a01d799003 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/InfinityFluidTank.java @@ -0,0 +1,82 @@ +package dev.dubhe.anvilcraft.api.fluidtank; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.templates.FluidTank; + +import java.util.function.Predicate; + +public class InfinityFluidTank extends FluidTank { + @Setter + @Getter + private boolean isInfinity; + + public InfinityFluidTank(int capacity, Predicate validator) { + this(capacity, validator, true); + } + + public InfinityFluidTank(int capacity, Predicate validator, boolean isInfinity) { + super(capacity, validator); + this.isInfinity = isInfinity; + } + + public InfinityFluidTank(int capacity) { + this(capacity, true); + } + + public InfinityFluidTank(int capacity, boolean isInfinity) { + super(capacity); + this.isInfinity = isInfinity; + } + + public FluidTank readFromNBT(HolderLookup.Provider lookupProvider, CompoundTag nbt) { + super.readFromNBT(lookupProvider, nbt); + this.isInfinity = nbt.getBoolean("Infinity"); + return this; + } + + public CompoundTag writeToNBT(HolderLookup.Provider lookupProvider, CompoundTag nbt) { + super.writeToNBT(lookupProvider, nbt); + nbt.putBoolean("Infinity", this.isInfinity); + return nbt; + } + + @Override + public FluidTank setCapacity(int capacity) { + super.setCapacity(capacity); + if (this.isInfinity && !this.fluid.isEmpty()) this.fluid.setAmount(this.capacity); + return this; + } + + @Override + public int fill(FluidStack resource, IFluidHandler.FluidAction action) { + if (!this.isInfinity) return super.fill(resource, action); + + if (resource.isEmpty() || !this.isFluidValid(resource)) return 0; + + if (!this.fluid.isEmpty() && !FluidStack.isSameFluidSameComponents(this.fluid, resource)) return 0; + + if (!action.simulate() && this.fluid.isEmpty()) { + this.fluid = resource.copyWithAmount(this.capacity); + this.onContentsChanged(); + } + return resource.getAmount(); + + } + + @Override + public FluidStack drain(int maxDrain, IFluidHandler.FluidAction action) { + if (!this.isInfinity) return super.drain(maxDrain, action); + + return this.isEmpty() ? FluidStack.EMPTY : this.fluid.copyWithAmount(maxDrain); + } + + @Override + public int getSpace() { + return isInfinity ? Integer.MAX_VALUE : super.getSpace(); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/package-info.java b/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/package-info.java new file mode 100644 index 0000000000..b61332633c --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/api/fluidtank/package-info.java @@ -0,0 +1,7 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package dev.dubhe.anvilcraft.api.fluidtank; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/ItemTooltipManager.java b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/ItemTooltipManager.java index b88e7ccb81..547e9dd0ee 100644 --- a/src/main/java/dev/dubhe/anvilcraft/api/tooltip/ItemTooltipManager.java +++ b/src/main/java/dev/dubhe/anvilcraft/api/tooltip/ItemTooltipManager.java @@ -63,6 +63,11 @@ public class ItemTooltipManager { "Attracting the anvil below, when pushed and pulled by the piston, causes adjacent copper blocks to generate charges"); map.put(ModBlocks.BATCH_CRAFTER.asItem(), "Received a redstone signal and synthesized all internal items at once, with a power consumption of 4 kW"); + map.put(ModBlocks.FISH_TANK.asItem(), """ + It is sturdier than it looks and can be used as a substitute for the alchemy pot to perform related anvil synthesis. + Wearing it on your head provides a temporary underwater breathing effect. + Right-click the top with an item in hand to place the item inside. + Right-click the lower part of the fish tank with a tropical fish bucket in hand to release the tropical fish."""); map.put(ModBlocks.ROYAL_STEEL_BLOCK.asItem(), "Explosion proof"); map.put(ModBlocks.SMOOTH_ROYAL_STEEL_BLOCK.asItem(), "Explosion proof"); map.put(ModBlocks.CUT_ROYAL_STEEL_BLOCK.asItem(), "Explosion proof"); diff --git a/src/main/java/dev/dubhe/anvilcraft/block/FishTankBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/FishTankBlock.java new file mode 100644 index 0000000000..0c6938f148 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/FishTankBlock.java @@ -0,0 +1,95 @@ +package dev.dubhe.anvilcraft.block; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.api.hammer.HammerRotateBehavior; +import dev.dubhe.anvilcraft.api.hammer.IHammerRemovable; +import dev.dubhe.anvilcraft.init.item.ModItemTags; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class FishTankBlock extends Block implements HammerRotateBehavior, IHammerRemovable { + public static final BooleanProperty TROPICAL = BooleanProperty.create("tropical"); + public static final BooleanProperty OUTLET = BooleanProperty.create("outlet"); + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + + public static final VoxelShape INPUT = box(2.0, 14.0, 2.0, 14.0, 16.0, 14.0); + public static final VoxelShape INSIDE = box(1.0, 1.0, 1.0, 15.0, 14.0, 15.0); + public static final VoxelShape SHAPE = Shapes.join(Shapes.block(), Shapes.join(INSIDE, INPUT, BooleanOp.OR), BooleanOp.ONLY_FIRST); + + public FishTankBlock(Properties properties) { + super(properties); + this.registerDefaultState(this.stateDefinition.any() + .setValue(TROPICAL, false) + .setValue(OUTLET, false) + .setValue(FACING, Direction.NORTH)); + } + + @Override + protected MapCodec codec() { + return simpleCodec(FishTankBlock::new); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(TROPICAL, OUTLET, FACING); + } + + @Override + protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SHAPE; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + Direction facing = context.getHorizontalDirection().getOpposite(); + return this.defaultBlockState().setValue(FACING, facing); + } + + @Override + protected ItemInteractionResult useItemOn( + ItemStack stack, + BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hitResult + ) { + if (!stack.is(ModItemTags.ANVIL_HAMMER)) { + return super.useItemOn(stack, state, level, pos, player, hand, hitResult); + } + // 切换 OUTLET 状态 + if (!level.isClientSide()) { + // 水平的四个方向根据被右键的方向转换 + Direction newOutletDirection = Direction.from2DDataValue((hitResult.getDirection().get2DDataValue())); + boolean newOutletValue = !state.getValue(OUTLET); + BlockState newState = state.setValue(OUTLET, newOutletValue).setValue(FACING, newOutletDirection); + + level.setBlock(pos, newState, 3); + level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 1.0f, 1.0f); + } + + return ItemInteractionResult.SUCCESS; + + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/block/FluidTankBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/FluidTankBlock.java new file mode 100644 index 0000000000..22c87c3fab --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/FluidTankBlock.java @@ -0,0 +1,77 @@ +package dev.dubhe.anvilcraft.block; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.api.hammer.HammerRotateBehavior; +import dev.dubhe.anvilcraft.api.hammer.IHammerRemovable; +import dev.dubhe.anvilcraft.block.entity.FluidTankBlockEntity; +import dev.dubhe.anvilcraft.init.block.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.Nullable; + +public class FluidTankBlock extends BaseEntityBlock implements HammerRotateBehavior, IHammerRemovable { + + public FluidTankBlock(Properties properties) { + super(properties); + } + + @Override + protected MapCodec codec() { + return simpleCodec(FluidTankBlock::new); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return ModBlockEntities.FLUID_TANK.create(pos, state); + } + + @Override + protected RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return createTickerHelper( + type, + ModBlockEntities.FLUID_TANK.get(), + (level1, blockPos, blockState, blockEntity) -> blockEntity.tick() + ); + } + + @Override + protected ItemInteractionResult useItemOn( + ItemStack stack, + BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hitResult + ) { + InteractionResult result = super.useItemOn(stack, state, level, pos, player, hand, hitResult).result(); + if (result == InteractionResult.PASS) { + if (level.getBlockEntity(pos) instanceof FluidTankBlockEntity tank) { + if (tank.onPlayerUse(player, hand)) { + return ItemInteractionResult.sidedSuccess(level.isClientSide()); + } + } + + } + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/block/LargeFluidTankBlock.java b/src/main/java/dev/dubhe/anvilcraft/block/LargeFluidTankBlock.java new file mode 100644 index 0000000000..f8cfe9d8e0 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/LargeFluidTankBlock.java @@ -0,0 +1,97 @@ +package dev.dubhe.anvilcraft.block; + +import dev.dubhe.anvilcraft.api.hammer.IHammerRemovable; +import dev.dubhe.anvilcraft.block.entity.LargeFluidTankBlockEntity; +import dev.dubhe.anvilcraft.block.multipart.SimpleMultiPartBlock; +import dev.dubhe.anvilcraft.block.state.Cube3x3PartHalf; +import dev.dubhe.anvilcraft.init.block.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.Nullable; + +import static dev.dubhe.anvilcraft.block.PropelPiston.createTickerHelper; + +public class LargeFluidTankBlock extends SimpleMultiPartBlock implements EntityBlock, IHammerRemovable { + public static final EnumProperty HALF = EnumProperty.create("half", Cube3x3PartHalf.class); + + public LargeFluidTankBlock(Properties properties) { + super(properties); + this.registerDefaultState(this.stateDefinition + .any() + .setValue(HALF, Cube3x3PartHalf.BOTTOM_CENTER)); + } + + @Override + public Vec3i getMainPartOffset() { + return new Vec3i(0, 1, 0); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(HALF); + } + + @Override + public Property getPart() { + return HALF; + } + + @Override + public Cube3x3PartHalf[] getParts() { + return Cube3x3PartHalf.values(); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return ModBlockEntities.LARGE_FLUID_TANK.create(blockPos, blockState); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + return createTickerHelper( + type, + ModBlockEntities.LARGE_FLUID_TANK.get(), + (level1, blockPos, blockState, blockEntity) -> blockEntity.tick() + ); + } + + @Override + protected ItemInteractionResult useItemOn( + ItemStack stack, + BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hitResult + ) { + InteractionResult result = super.useItemOn(stack, state, level, pos, player, hand, hitResult).result(); + if (result == InteractionResult.PASS) { + if (level.getBlockEntity(pos) instanceof LargeFluidTankBlockEntity tank) { + if (tank.onPlayerUse(player, hand)) { + return ItemInteractionResult.sidedSuccess(level.isClientSide()); + } + } + } + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/FluidTankBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/FluidTankBlockEntity.java new file mode 100644 index 0000000000..b30a325d0f --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/FluidTankBlockEntity.java @@ -0,0 +1,91 @@ +package dev.dubhe.anvilcraft.block.entity; + +import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; +import dev.dubhe.anvilcraft.util.TankUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.fluids.FluidUtil; +import net.neoforged.neoforge.fluids.IFluidTank; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.templates.FluidTank; + +public class FluidTankBlockEntity extends BlockEntity implements IFluidHandlerHolder { + public static final int CAPACITY = 16 * FluidType.BUCKET_VOLUME; + public static final int BIG_CAPACITY = 640 * FluidType.BUCKET_VOLUME; + public static final int COOLDOWN = 100; + protected FluidTank tank = new FluidTank(CAPACITY); + protected int cooldown = 0; + + public FluidTankBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + public void tick() { + if (--cooldown <= 0) { + checkStructure(); + cooldown = COOLDOWN; + } + setChanged(); + } + + protected void checkStructure() { + if (this.getLevel() == null) return; + + int targetCapacity = TankUtil.isMengerStructure(this.getLevel(), this.getBlockPos(), 3) ? BIG_CAPACITY : CAPACITY; + if (tank.getCapacity() != targetCapacity) { + tank.setCapacity(targetCapacity); + } + } + + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.saveAdditional(tag, provider); + CompoundTag tankNbt = tank.writeToNBT(provider, new CompoundTag()); + if (!tankNbt.isEmpty()) { + tag.put("tank", tankNbt); + } + } + + @Override + public void loadAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.loadAdditional(tag, provider); + tank.readFromNBT(provider, tag.getCompound("tank")); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + CompoundTag tag = super.getUpdateTag(registries); + CompoundTag fluidTag = new CompoundTag(); + tank.writeToNBT(registries, fluidTag); + tag.put("tank", fluidTag); + return tag; + } + + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + public boolean onPlayerUse(Player player, InteractionHand hand) { + checkStructure(); + return FluidUtil.interactWithFluidHandler(player, hand, tank); + } + + public IFluidTank getTank() { + return tank; + } + + public IFluidHandler getFluidHandler() { + return tank; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/LargeFluidTankBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/LargeFluidTankBlockEntity.java new file mode 100644 index 0000000000..a1ff31e6e2 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/LargeFluidTankBlockEntity.java @@ -0,0 +1,116 @@ +package dev.dubhe.anvilcraft.block.entity; + +import dev.dubhe.anvilcraft.api.fluid.IFluidHandlerHolder; +import dev.dubhe.anvilcraft.api.fluidtank.InfinityFluidTank; +import dev.dubhe.anvilcraft.block.LargeFluidTankBlock; +import dev.dubhe.anvilcraft.block.state.Cube3x3PartHalf; +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import dev.dubhe.anvilcraft.util.TankUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.fluids.FluidType; +import net.neoforged.neoforge.fluids.FluidUtil; +import net.neoforged.neoforge.fluids.IFluidTank; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +public class LargeFluidTankBlockEntity extends BlockEntity implements IFluidHandlerHolder { + public static final int CAPACITY = 320 * FluidType.BUCKET_VOLUME; + public static final int BIG_CAPACITY = 12800 * FluidType.BUCKET_VOLUME; + public static final int COOLDOWN = 100; + protected InfinityFluidTank tank = new InfinityFluidTank(CAPACITY, false); + protected int cooldown = 0; + + public LargeFluidTankBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + public void tick() { + BlockState state = getBlockState(); + if (!state.getValue(LargeFluidTankBlock.HALF).equals(Cube3x3PartHalf.MID_CENTER)) return; + if (--cooldown <= 0) { + checkStructure(); + cooldown = COOLDOWN; + } + setChanged(); + } + + protected void checkStructure() { + if (this.getLevel() == null) return; + if (!this.isMainPart()) { + this.getMainPart().checkStructure(); + return; + } + + if (TankUtil.isMengerStructure(this.getLevel(), this.getBlockPos(), 9)) { + tank.setCapacity(BIG_CAPACITY); + if (tank.getSpace() <= 0) tank.setInfinity(true); + } else { + tank.setInfinity(false); + tank.setCapacity(CAPACITY); + } + } + + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.saveAdditional(tag, provider); + CompoundTag tankNbt = tank.writeToNBT(provider, new CompoundTag()); + if (!tankNbt.isEmpty()) { + tag.put("tank", tankNbt); + } + } + + @Override + public void loadAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.loadAdditional(tag, provider); + tank.readFromNBT(provider, tag.getCompound("tank")); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + CompoundTag tag = super.getUpdateTag(registries); + CompoundTag fluidTag = new CompoundTag(); + tank.writeToNBT(registries, fluidTag); + tag.put("tank", fluidTag); + return tag; + } + + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + public boolean onPlayerUse(Player player, InteractionHand hand) { + checkStructure(); + return FluidUtil.interactWithFluidHandler(player, hand, this.getFluidHandler()); + } + + public IFluidTank getTank() { + return getMainPart().tank; + } + + public IFluidHandler getFluidHandler() { + return getMainPart().tank; + } + + public boolean isMainPart() { + LargeFluidTankBlock block = ModBlocks.LARGE_FLUID_TANK.get(); + return block.isMainPart(this.getBlockState()); + } + + public LargeFluidTankBlockEntity getMainPart() { + LargeFluidTankBlock block = ModBlocks.LARGE_FLUID_TANK.get(); + BlockPos mainPartPos = block.getMainPartPos(this.getBlockPos(), this.getBlockState()); + if (this.getLevel() == null) return this; + BlockEntity mainPart = this.getLevel().getBlockEntity(mainPartPos); + return mainPart instanceof LargeFluidTankBlockEntity ? (LargeFluidTankBlockEntity) mainPart : this; + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/FluidTankBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/FluidTankBlockEntityRenderer.java new file mode 100644 index 0000000000..0642044b95 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/FluidTankBlockEntityRenderer.java @@ -0,0 +1,89 @@ +/* + * Original Code Copyright (C) 2013 - 2020 AlgorithmX2 et al + * Source: https://github.com/AppliedEnergistics/Applied-Energistics-2 + * + * This file is part of "Applied Energistics 2" project, which is licensed under + * the GNU Lesser General Public License Version 3 (LGPLv3). + * + * --- MODIFICATIONS --- + * This file has been modified for use in AnvilCraft. + * Modifications made by: TB_pig + * Modification date: 2026/2/12 + * These modifications continue to be licensed under LGPLv3. + * ------------------------------------------------------------- + */ + +package dev.dubhe.anvilcraft.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.dubhe.anvilcraft.block.entity.FluidTankBlockEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.world.inventory.InventoryMenu; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidType; + +import static dev.dubhe.anvilcraft.client.renderer.blockentity.LargeFluidTankBlockEntityRenderer.renderFluidCube; + +public class FluidTankBlockEntityRenderer implements BlockEntityRenderer { + public FluidTankBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + public void render( + FluidTankBlockEntity tank, float tickDelta, PoseStack ms, MultiBufferSource vertexConsumers, int light, int overlay) { + if (tank.getTank().getFluid().isEmpty()) return; + + /* + * + * // Uncomment to allow the liquid to rotate with the tank ms.pushPose(); ms.translate(0.5, 0.5, 0.5); + * FacingToRotation.get(tank.getForward(), tank.getUp()).push(ms); ms.translate(-0.5, -0.5, -0.5); + */ + float fill = (float) tank.getTank().getFluid().getAmount() / tank.getTank().getCapacity(); + + drawFluidInTank( + ms, + vertexConsumers, + light, + tank.getTank().getFluid(), + fill + ); + + // ms.popPose(); + } + + private static final float TANK_W = 1 / 16f + 0.001f; // avoiding Z-fighting + + public static void drawFluidInTank(PoseStack ps, MultiBufferSource mbs, int light, FluidStack fluid, float fill) { + // From Modern Industrialization + var renderProps = IClientFluidTypeExtensions.of(fluid.getFluid()); + TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS) + .apply(renderProps.getStillTexture(fluid)); + + int color = renderProps.getTintColor(fluid); + + // Top and bottom positions of the fluid inside the tank + float height = 1 - 2 * TANK_W; + + float minX = TANK_W; + float minY = TANK_W; + float minZ = TANK_W; + float maxX = 1 - TANK_W; + float maxY = 1 - TANK_W; + float maxZ = 1 - TANK_W; + + FluidType attributes = fluid.getFluid().getFluidType(); + if (attributes.isLighterThanAir()) { + minY = maxY - fill * height; + } else { + maxY = minY + fill * height; + } + + renderFluidCube(ps, mbs, light, sprite, color, minX, minY, minZ, maxX, maxY, maxZ); + } + +} diff --git a/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/LargeFluidTankBlockEntityRenderer.java b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/LargeFluidTankBlockEntityRenderer.java new file mode 100644 index 0000000000..d031fbdadb --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/LargeFluidTankBlockEntityRenderer.java @@ -0,0 +1,273 @@ +/* + * Original Code Copyright (C) 2013 - 2020 AlgorithmX2 et al + * Source: https://github.com/AppliedEnergistics/Applied-Energistics-2 + * + * This file is part of "Applied Energistics 2" project, which is licensed under + * the GNU Lesser General Public License Version 3 (LGPLv3). + * + * --- MODIFICATIONS --- + * This file has been modified for use in AnvilCraft. + * Modifications made by: TB_pig + * Modification date: 2026/2/12 + * These modifications continue to be licensed under LGPLv3. + * ------------------------------------------------------------- + */ + +package dev.dubhe.anvilcraft.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import dev.dubhe.anvilcraft.block.entity.LargeFluidTankBlockEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import net.minecraft.world.inventory.InventoryMenu; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidType; +import org.joml.Matrix4f; + +public class LargeFluidTankBlockEntityRenderer implements BlockEntityRenderer { + public LargeFluidTankBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + public void render( + LargeFluidTankBlockEntity tank, float tickDelta, PoseStack ms, MultiBufferSource vertexConsumers, int light, int overlay) { + if (tank.getTank().getFluid().isEmpty()) return; + if (!tank.isMainPart()) return; + + /* + * + * // Uncomment to allow the liquid to rotate with the tank ms.pushPose(); ms.translate(0.5, 0.5, 0.5); + * FacingToRotation.get(tank.getForward(), tank.getUp()).push(ms); ms.translate(-0.5, -0.5, -0.5); + */ + float fill = (float) tank.getTank().getFluid().getAmount() / tank.getTank().getCapacity(); + if (fill <= 0.025) fill = 0.025f; + + drawFluidInTank(ms, vertexConsumers, light, tank.getTank().getFluid(), fill); + + // ms.popPose(); + } + + private static final float TANK_W = 4 / 16f + 0.001f; // avoiding Z-fighting + + public static void drawFluidInTank(PoseStack ps, MultiBufferSource mbs, int light, FluidStack fluid, float fill) { + // From Modern Industrialization + var renderProps = IClientFluidTypeExtensions.of(fluid.getFluid()); + TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS) + .apply(renderProps.getStillTexture(fluid)); + + int color = renderProps.getTintColor(fluid); + + // Top and bottom positions of the fluid inside the tank + float height = 3 - 2 * TANK_W; + + float minX = TANK_W - 1; + float minY = TANK_W - 1; + float minZ = TANK_W - 1; + float maxX = 2 - TANK_W; + float maxY = 2 - TANK_W; + float maxZ = 2 - TANK_W; + + FluidType attributes = fluid.getFluid().getFluidType(); + if (attributes.isLighterThanAir()) { + minY = maxY - fill * height; + } else { + maxY = minY + fill * height; + } + + // 使用平移复制裁切方式渲染液体材质 + renderFluidCube(ps, mbs, light, sprite, color, minX, minY, minZ, maxX, maxY, maxZ); + } + + public static void renderFluidCube( + PoseStack ps, + MultiBufferSource mbs, + int light, + TextureAtlasSprite sprite, + int color, + float minX, + float minY, + float minZ, + float maxX, + float maxY, + float maxZ + ) { + VertexConsumer consumer = mbs.getBuffer(RenderType.translucent()); + Matrix4f pose = ps.last().pose(); + RenderManager renderManager = new RenderManager(consumer, light, sprite, pose, color, minX, minY, minZ, maxX, maxY, maxZ); + renderManager.render(); + } + + public static class RenderManager { + protected VertexConsumer consumer; + protected int light; + protected Matrix4f pose; + protected int color; + protected float minX; + protected float minY; + protected float minZ; + protected float maxX; + protected float maxY; + protected float maxZ; + protected float u0; + protected float u1; + protected float v0; + protected float v1; + protected float ul; + protected float vl; + + public RenderManager( + VertexConsumer consumer, + int light, + TextureAtlasSprite sprite, + Matrix4f pose, + int color, + float minX, + float minY, + float minZ, + float maxX, + float maxY, + float maxZ + ) { + this.consumer = consumer; + this.light = light; + this.pose = pose; + this.u0 = sprite.getU0(); + this.u1 = sprite.getU1(); + this.v0 = sprite.getV0(); + this.v1 = sprite.getV1(); + this.ul = this.u1 - this.u0; + this.vl = this.v1 - this.v0; + this.color = color; + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + } + + public void render() { + renderSide(Direction.NORTH); + renderSide(Direction.SOUTH); + renderSide(Direction.WEST); + renderSide(Direction.EAST); + renderSide(Direction.UP); + renderSide(Direction.DOWN); + } + + public void renderSide(Direction direction) { + float[] normal = { + 0, + 0, + 0 + }; + float minSideI; + float minSideJ; + float maxSideI; + float maxSideJ; + switch (direction) { + case NORTH -> { + normal[2] = -1; + minSideI = minX; + maxSideI = maxX; + minSideJ = minY; + maxSideJ = maxY; + } + case SOUTH -> { + normal[2] = 1; + minSideI = minX; + maxSideI = maxX; + minSideJ = minY; + maxSideJ = maxY; + } + case WEST -> { + normal[0] = -1; + minSideI = minY; + maxSideI = maxY; + minSideJ = minZ; + maxSideJ = maxZ; + } + case EAST -> { + normal[0] = 1; + minSideI = minY; + maxSideI = maxY; + minSideJ = minZ; + maxSideJ = maxZ; + } + case UP -> { + normal[1] = 1; + minSideI = minX; + maxSideI = maxX; + minSideJ = minZ; + maxSideJ = maxZ; + } + default -> { + normal[1] = -1; + minSideI = minX; + maxSideI = maxX; + minSideJ = minZ; + maxSideJ = maxZ; + } + } + for (float minI = minSideI; minI < maxSideI; minI += 1) { + float maxI = Math.min(minI + 1, maxSideI); + float v0 = this.v0; + float v1 = this.v0 + (maxI - minI) * this.vl; + for (float minJ = minSideJ; minJ < maxSideJ; minJ += 1) { + float maxJ = Math.min(minJ + 1, maxSideJ); + float u0 = this.u0; + float u1 = this.u0 + (maxJ - minJ) * this.ul; + switch (direction) { + case NORTH -> { + addVertex(maxI, maxJ, minZ, u0, v0, normal); + addVertex(maxI, minJ, minZ, u1, v0, normal); + addVertex(minI, minJ, minZ, u1, v1, normal); + addVertex(minI, maxJ, minZ, u0, v1, normal); + } + case SOUTH -> { + addVertex(maxI, minJ, maxZ, u0, v0, normal); + addVertex(maxI, maxJ, maxZ, u1, v0, normal); + addVertex(minI, maxJ, maxZ, u1, v1, normal); + addVertex(minI, minJ, maxZ, u0, v1, normal); + } + case WEST -> { + addVertex(minX, maxI, maxJ, u0, v0, normal); + addVertex(minX, maxI, minJ, u1, v0, normal); + addVertex(minX, minI, minJ, u1, v1, normal); + addVertex(minX, minI, maxJ, u0, v1, normal); + } + case EAST -> { + addVertex(maxX, minI, maxJ, u0, v0, normal); + addVertex(maxX, minI, minJ, u1, v0, normal); + addVertex(maxX, maxI, minJ, u1, v1, normal); + addVertex(maxX, maxI, maxJ, u0, v1, normal); + } + case UP -> { + addVertex(maxI, maxY, maxJ, u0, v0, normal); + addVertex(maxI, maxY, minJ, u1, v0, normal); + addVertex(minI, maxY, minJ, u1, v1, normal); + addVertex(minI, maxY, maxJ, u0, v1, normal); + } + default -> { + addVertex(maxI, minY, maxJ, u0, v0, normal); + addVertex(maxI, minY, minJ, u1, v0, normal); + addVertex(minI, minY, minJ, u1, v1, normal); + addVertex(minI, minY, maxJ, u0, v1, normal); + } + } + } + } + } + + public void addVertex(float x, float y, float z, float u, float v, float[] normal) { + consumer.addVertex(pose, x, y, z).setColor(color).setUv(u, v).setLight(light).setNormal(normal[0], normal[1], normal[2]); + } + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockConversionRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockConversionRecipeLoader.java index f70e785966..f7b6e0c228 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockConversionRecipeLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockConversionRecipeLoader.java @@ -422,6 +422,244 @@ public static void init(RegistrateRecipeProvider provider) { ) .save(provider, AnvilCraft.of("multiblock_conversion/giant_anvil_2")); + + MultiblockConversionRecipe.builder() + .inputLayer("AAA", "AAA", "AAA") + .inputLayer("AAA", "AAA", "AAA") + .inputLayer("AAA", "AAA", "AAA") + .inputSymbol('A', ModBlocks.FLUID_TANK) + .outputLayer("ABC", "DEF", "GHI") + .outputLayer("JKL", "MNO", "PQR") + .outputLayer("STU", "VWX", "YZ[") + .outputSymbol( + 'A', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_WN) + ) + .outputSymbol( + 'B', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_N) + ) + .outputSymbol( + 'C', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_EN) + ) + .outputSymbol( + 'D', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_W) + ) + .outputSymbol( + 'E', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_CENTER) + ) + .outputSymbol( + 'F', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_E) + ) + .outputSymbol( + 'G', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_WS) + ) + .outputSymbol( + 'H', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_S) + ) + .outputSymbol( + 'I', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_ES) + ) + .outputSymbol( + 'J', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_WN) + ) + .outputSymbol( + 'K', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_N) + ) + .outputSymbol( + 'L', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_EN) + ) + .outputSymbol( + 'M', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_W) + ) + .outputSymbol( + 'N', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_CENTER) + ) + .outputSymbol( + 'O', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_E) + ) + .outputSymbol( + 'P', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_WS) + ) + .outputSymbol( + 'Q', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_S) + ) + .outputSymbol( + 'R', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_ES) + ) + .outputSymbol( + 'S', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_WN) + ) + .outputSymbol( + 'T', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_N) + ) + .outputSymbol( + 'U', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_EN) + ) + .outputSymbol( + 'V', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_W) + ) + .outputSymbol( + 'W', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_CENTER) + ) + .outputSymbol( + 'X', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_E) + ) + .outputSymbol( + 'Y', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_WS) + ) + .outputSymbol( + 'Z', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_S) + ) + .outputSymbol( + '[', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_ES) + ) + .save(provider, AnvilCraft.of("multiblock_conversion/large_fluid_tank_1")); + + MultiblockConversionRecipe.builder() + .inputLayer("AAA", "AAA", "AAA") + .inputLayer("AAA", "A A", "AAA") + .inputLayer("AAA", "AAA", "AAA") + .inputSymbol('A', ModBlocks.FLUID_TANK) + .outputLayer("ABC", "DEF", "GHI") + .outputLayer("JKL", "MNO", "PQR") + .outputLayer("STU", "VWX", "YZ[") + .outputSymbol( + 'A', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_WN) + ) + .outputSymbol( + 'B', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_N) + ) + .outputSymbol( + 'C', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_EN) + ) + .outputSymbol( + 'D', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_W) + ) + .outputSymbol( + 'E', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_CENTER) + ) + .outputSymbol( + 'F', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_E) + ) + .outputSymbol( + 'G', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_WS) + ) + .outputSymbol( + 'H', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_S) + ) + .outputSymbol( + 'I', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.BOTTOM_ES) + ) + .outputSymbol( + 'J', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_WN) + ) + .outputSymbol( + 'K', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_N) + ) + .outputSymbol( + 'L', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_EN) + ) + .outputSymbol( + 'M', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_W) + ) + .outputSymbol( + 'N', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_CENTER) + ) + .outputSymbol( + 'O', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_E) + ) + .outputSymbol( + 'P', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_WS) + ) + .outputSymbol( + 'Q', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_S) + ) + .outputSymbol( + 'R', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.MID_ES) + ) + .outputSymbol( + 'S', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_WN) + ) + .outputSymbol( + 'T', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_N) + ) + .outputSymbol( + 'U', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_EN) + ) + .outputSymbol( + 'V', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_W) + ) + .outputSymbol( + 'W', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_CENTER) + ) + .outputSymbol( + 'X', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_E) + ) + .outputSymbol( + 'Y', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_WS) + ) + .outputSymbol( + 'Z', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_S) + ) + .outputSymbol( + '[', BlockPredicateWithState.of(ModBlocks.LARGE_FLUID_TANK) + .hasState(GiantAnvilBlock.HALF, Cube3x3PartHalf.TOP_ES) + ) + .save(provider, AnvilCraft.of("multiblock_conversion/large_fluid_tank_2")); + + MultiblockConversionRecipe.builder() .inputLayer("ABA", "B B", "ABA") .inputLayer("CDC", "D D", "CDC") diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockRecipeLoader.java index 5bd77defc0..6764ebede8 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockRecipeLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/MultiBlockRecipeLoader.java @@ -69,6 +69,20 @@ public static void init(RegistrateRecipeProvider provider) { .symbol('C', ModBlocks.POLISHED_HEAVY_IRON_BLOCK) .save(provider, AnvilCraft.of("multiblock/giant_anvil_2")); + MultiblockRecipe.builder(ModBlocks.LARGE_FLUID_TANK) + .layer("AAA", "AAA", "AAA") + .layer("AAA", "AAA", "AAA") + .layer("AAA", "AAA", "AAA") + .symbol('A', ModBlocks.FLUID_TANK) + .save(provider, AnvilCraft.of("multiblock/large_fluid_tank_1")); + + MultiblockRecipe.builder(ModBlocks.LARGE_FLUID_TANK) + .layer("AAA", "AAA", "AAA") + .layer("AAA", "A A", "AAA") + .layer("AAA", "AAA", "AAA") + .symbol('A', ModBlocks.FLUID_TANK) + .save(provider, AnvilCraft.of("multiblock/large_fluid_tank_2")); + MultiblockRecipe.builder(ModBlocks.MENGER_SPONGE) .layer("AAA", "A A", "AAA") .layer("A A", " B ", "A A") diff --git a/src/main/java/dev/dubhe/anvilcraft/data/tags/FluidTagLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/tags/FluidTagLoader.java index 11a644c654..788dd7c3d3 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/tags/FluidTagLoader.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/tags/FluidTagLoader.java @@ -31,6 +31,7 @@ public static void init(RegistrateTagsProvider provider) { .add(ModFluids.FLOWING_OIL.getKey()) .add(ModFluids.MELT_GEM.getKey()) .add(ModFluids.FLOWING_MELT_GEM.getKey()) + .add(ModFluids.EXP_FLUID.getKey()) .addTag(ModFluidTags.CEMENT); provider.addTag(ModFluidTags.OIL) .add(findResourceKey(ModFluids.OIL.get())) diff --git a/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java index 4e2ce32c4e..6718f8620b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/CapabilitiesEventListener.java @@ -15,7 +15,8 @@ public class CapabilitiesEventListener { @SubscribeEvent public static void registerCapabilities(final RegisterCapabilitiesEvent event) { - List.of(ModBlockEntities.BATCH_CRAFTER.get(), + List.of( + ModBlockEntities.BATCH_CRAFTER.get(), ModBlockEntities.CHARGER.get(), ModBlockEntities.CHUTE.get(), ModBlockEntities.SIMPLE_CHUTE.get(), @@ -23,9 +24,10 @@ public static void registerCapabilities(final RegisterCapabilitiesEvent event) { ModBlockEntities.MAGNETIC_CHUTE.get(), ModBlockEntities.CONFINEMENT_CHAMBER.get() ).forEach(type -> event.registerBlockEntity( - Capabilities.ItemHandler.BLOCK, - type, - (be, side) -> be.getItemHandler()) + Capabilities.ItemHandler.BLOCK, + type, + (be, side) -> be.getItemHandler() + ) ); event.registerBlock( @@ -33,5 +35,16 @@ public static void registerCapabilities(final RegisterCapabilitiesEvent event) { ((level, pos, state, blockEntity, side) -> new HoneyCauldronWrapper(level, pos)), ModBlocks.HONEY_CAULDRON.get() ); + + List.of( + ModBlockEntities.FLUID_TANK.get(), + ModBlockEntities.LARGE_FLUID_TANK.get() + ).forEach(type -> event.registerBlockEntity( + Capabilities.FluidHandler.BLOCK, + type, + (be, side) -> be.getFluidHandler() + )); + + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java index 7a20581f83..ffbd39040b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlockEntities.java @@ -16,12 +16,14 @@ import dev.dubhe.anvilcraft.block.entity.CreativeGeneratorBlockEntity; import dev.dubhe.anvilcraft.block.entity.DeflectionRingBlockEntity; import dev.dubhe.anvilcraft.block.entity.DetectorSlidingRailBlockEntity; +import dev.dubhe.anvilcraft.block.entity.FluidTankBlockEntity; import dev.dubhe.anvilcraft.block.entity.HeatCollectorBlockEntity; import dev.dubhe.anvilcraft.block.entity.HeaterBlockEntity; import dev.dubhe.anvilcraft.block.entity.HeliostatsBlockEntity; import dev.dubhe.anvilcraft.block.entity.InductionLightBlockEntity; import dev.dubhe.anvilcraft.block.entity.ItemCollectorBlockEntity; import dev.dubhe.anvilcraft.block.entity.ItemDetectorBlockEntity; +import dev.dubhe.anvilcraft.block.entity.LargeFluidTankBlockEntity; import dev.dubhe.anvilcraft.block.entity.LaserReceiverBlockEntity; import dev.dubhe.anvilcraft.block.entity.LoadMonitorBlockEntity; import dev.dubhe.anvilcraft.block.entity.MagneticChuteBlockEntity; @@ -56,9 +58,11 @@ import dev.dubhe.anvilcraft.client.renderer.blockentity.ConfinementChamberRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.CorruptedBeaconRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.CreativeGeneratorRenderer; +import dev.dubhe.anvilcraft.client.renderer.blockentity.FluidTankBlockEntityRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.HasMobBlockRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.HeatCollectorRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.HeliostatsRenderer; +import dev.dubhe.anvilcraft.client.renderer.blockentity.LargeFluidTankBlockEntityRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.LaserBlockRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.PlasmaJetsRenderer; import dev.dubhe.anvilcraft.client.renderer.blockentity.VoidEnergyCollectorRenderer; @@ -304,6 +308,18 @@ public class ModBlockEntities { .validBlocks(ModBlocks.NEUTRON_IRRADIATOR) .register(); + public static final BlockEntityEntry FLUID_TANK = REGISTRATE + .blockEntity("fluid_tank", FluidTankBlockEntity::new) + .validBlocks(ModBlocks.FLUID_TANK) + .renderer(() -> FluidTankBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry LARGE_FLUID_TANK = REGISTRATE + .blockEntity("large_fluid_tank", LargeFluidTankBlockEntity::new) + .validBlocks(ModBlocks.LARGE_FLUID_TANK) + .renderer(() -> LargeFluidTankBlockEntityRenderer::new) + .register(); + public static void register() { } } 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 cc74adb801..a585b7fa57 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/block/ModBlocks.java @@ -46,7 +46,9 @@ import dev.dubhe.anvilcraft.block.ExpFluidCauldronBlock; import dev.dubhe.anvilcraft.block.FerriteCoreMagnetBlock; import dev.dubhe.anvilcraft.block.FireCauldronBlock; +import dev.dubhe.anvilcraft.block.FishTankBlock; import dev.dubhe.anvilcraft.block.FlintBlock; +import dev.dubhe.anvilcraft.block.FluidTankBlock; import dev.dubhe.anvilcraft.block.FrostAnvilBlock; import dev.dubhe.anvilcraft.block.FrostGrindstoneBlock; import dev.dubhe.anvilcraft.block.FrostMetalBlock; @@ -72,6 +74,7 @@ import dev.dubhe.anvilcraft.block.ItemDetectorBlock; import dev.dubhe.anvilcraft.block.JewelCraftingTable; import dev.dubhe.anvilcraft.block.LargeCakeBlock; +import dev.dubhe.anvilcraft.block.LargeFluidTankBlock; import dev.dubhe.anvilcraft.block.LaserReceiverBlock; import dev.dubhe.anvilcraft.block.LavaCauldronBlock; import dev.dubhe.anvilcraft.block.LevitationPowderBlock; @@ -176,6 +179,7 @@ import dev.dubhe.anvilcraft.init.item.ModItemGroups; import dev.dubhe.anvilcraft.init.item.ModItemTags; import dev.dubhe.anvilcraft.init.item.ModItems; +import dev.dubhe.anvilcraft.item.FishTankBlockItem; import dev.dubhe.anvilcraft.item.TeslaTowerItem; import dev.dubhe.anvilcraft.recipe.anvil.wrap.ItemInjectRecipe; import dev.dubhe.anvilcraft.recipe.multiblock.MultiblockRecipe; @@ -358,6 +362,39 @@ public class ModBlocks { }) .register(); + public static final BlockEntry FISH_TANK = REGISTRATE.block("fish_tank", FishTankBlock::new) + .initialProperties(() -> Blocks.CAULDRON) + .blockstate(DataGenUtil::noExtraModelOrState) + .item(FishTankBlockItem::new) + .build() + .tag(BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.CAULDRONS) + .recipe((ctx, provider) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get()) + .pattern("A A") + .pattern("B B") + .pattern("BBB") + .define('A', Items.IRON_INGOT) + .define('B', Tags.Items.GLASS_PANES) + .unlockedBy(AnvilCraftDatagen.hasItem(Items.IRON_INGOT), AnvilCraftDatagen.has(Items.IRON_INGOT)) + .save(provider); + }) + .register(); + + public static final BlockEntry FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::new) + .initialProperties(() -> Blocks.IRON_BLOCK) + .properties(p -> p.noOcclusion().isValidSpawn(Blocks::never)) + .blockstate(DataGenUtil::noExtraModelOrState) + .simpleItem() + .tag(BlockTags.MINEABLE_WITH_PICKAXE) + .recipe((ctx, provider) -> { + ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ctx.get(), 2) + .requires(ModItemTags.BRASS_PLATES) + .requires(ModBlocks.FISH_TANK) + .unlockedBy(AnvilCraftDatagen.hasItem(ModBlocks.FISH_TANK.asItem()), AnvilCraftDatagen.has(ModBlocks.FISH_TANK)) + .save(provider); + }) + .register(); + public static final BlockEntry CORRUPTED_BEACON = REGISTRATE.block("corrupted_beacon", CorruptedBeaconBlock::new) .initialProperties(() -> Blocks.BEACON) .properties(p -> p.isValidSpawn(Blocks::never)) @@ -1712,6 +1749,20 @@ public class ModBlocks { }) .register(); + public static final BlockEntry LARGE_FLUID_TANK = REGISTRATE.block( + "large_fluid_tank", + LargeFluidTankBlock::new + ) + .initialProperties(() -> Blocks.IRON_BLOCK) + .properties(p -> p.isSuffocating(ModBlocks::never).isSuffocating(ModBlocks::never).noOcclusion().isValidSpawn(Blocks::never)) + .loot(SimpleMultiPartBlock::loot) + .item(SimpleMultiPartBlockItem::new) + .properties((properties) -> properties.stacksTo(16)) + .build() + .blockstate(DataGenUtil::noExtraModelOrState) + .tag(BlockTags.MINEABLE_WITH_PICKAXE) + .register(); + public static final BlockEntry ACCELERATION_RING = REGISTRATE.block( "acceleration_ring", AccelerationRingBlock::new @@ -2985,7 +3036,6 @@ public class ModBlocks { }) .register(); - public static final BlockEntry RESIN_BLOCK = REGISTRATE.block("resin_block", ResinBlock::new) .lang("Block of Resin") .initialProperties(() -> Blocks.SLIME_BLOCK) diff --git a/src/main/java/dev/dubhe/anvilcraft/item/FishTankBlockItem.java b/src/main/java/dev/dubhe/anvilcraft/item/FishTankBlockItem.java new file mode 100644 index 0000000000..1e094c3931 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/item/FishTankBlockItem.java @@ -0,0 +1,40 @@ +package dev.dubhe.anvilcraft.item; + +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Equipable; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; + +public class FishTankBlockItem extends BlockItem implements Equipable { + public FishTankBlockItem(Block block, Properties properties) { + super(block, properties); + } + + @Override + public EquipmentSlot getEquipmentSlot() { + return EquipmentSlot.HEAD; + } + + @Override + public boolean canEquip(ItemStack stack, EquipmentSlot armorType, LivingEntity entity) { + return armorType == EquipmentSlot.HEAD; + } + + @Override + public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { + super.inventoryTick(stack, level, entity, slotId, isSelected); + if (level.isClientSide()) return; + if (!(entity instanceof Player player)) return; + ItemStack headSlot = player.getItemBySlot(EquipmentSlot.HEAD); + if (!headSlot.getItem().equals(ModBlocks.FISH_TANK.asItem()) || player.isInWater()) return; + player.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 601, 0, false, false)); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/util/TankUtil.java b/src/main/java/dev/dubhe/anvilcraft/util/TankUtil.java new file mode 100644 index 0000000000..7fb266594b --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/util/TankUtil.java @@ -0,0 +1,90 @@ +package dev.dubhe.anvilcraft.util; + +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +import java.util.List; + +public class TankUtil { + /** + * 递归检测当前位置的结构是否符合门格海绵结构 + * 门格海绵结构规则:将结构分为3x3x3的块后, + * 角块和边块应该是门格海绵方块,面块和中心块应该是空气 + * + * @param level 世界对象 + * @param centerPos 检测起始位置 + * @param size 结构大小(必须是3的倍数) + * @return 是否符合门格海绵结构 + */ + public static boolean isMengerStructure(Level level, BlockPos centerPos, int size) { + if (size <= 0) return false; + + // 基础情况:如果size为1,则直接检查是否为门格海绵 + if (size == 1) { + return level.getBlockState(centerPos).is(ModBlocks.MENGER_SPONGE.get()); + } + + if (size % 3 != 0) return false; + // 递归情况:将大结构分解为27个小结构进行检查 + int subSize = size / 3; + + for (int x = -1; x < 2; x++) { + for (int y = -1; y < 2; y++) { + for (int z = -1; z < 2; z++) { + BlockPos subPos = centerPos.offset(x * subSize, y * subSize, z * subSize); + + if (isMengerPos(x, y, z)) { + // 角块和边块应该符合门格海绵结构 + if (!isMengerStructure(level, subPos, subSize)) { + return false; + } + } else { + // 面块和中心块应该是空气 + if (!isNoMengerSponge(level, subPos, subSize)) { + return false; + } + } + } + } + } + + return true; + } + + public static boolean isNoMengerSponge(Level level, BlockPos centerPos, int size) { + if (size <= 0) return false; + if (size % 2 == 0) return false; + int delta = size / 2; + List blockPosList = BlockPos.betweenClosedStream( + centerPos.getX() - delta, + centerPos.getY() - delta, + centerPos.getZ() - delta, + centerPos.getX() + delta, + centerPos.getY() + delta, + centerPos.getZ() + delta + ) + .map(BlockPos::immutable) + .toList(); + for (BlockPos subPos : blockPosList) { + if (level.getBlockState(subPos).is(ModBlocks.MENGER_SPONGE.get())) { + return false; + } + } + return true; + } + + /** + * 判断在3x3x3结构中的位置是否为角块或边块 + */ + public static boolean isMengerPos(int x, int y, int z) { + int sideCount = 0; + if (x != 0) sideCount++; + if (y != 0) sideCount++; + if (z != 0) sideCount++; + + // 角块:至少两个坐标是-1或1 + // 边块:恰好一个坐标是-1或1 + return sideCount >= 2; + } +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft/blockstates/fish_tank.json b/src/main/resources/assets/anvilcraft/blockstates/fish_tank.json new file mode 100644 index 0000000000..888cfb5315 --- /dev/null +++ b/src/main/resources/assets/anvilcraft/blockstates/fish_tank.json @@ -0,0 +1,60 @@ +{ + "multipart": [ + { + "when": { + "tropical": "false" + }, + "apply": { + "model": "anvilcraft:block/fish_tank" + } + }, + { + "when": { + "tropical": "true" + }, + "apply": { + "model": "anvilcraft:block/tropical_fish_tank" + } + }, + { + "when": { + "outlet": "true", + "facing": "north" + }, + "apply": { + "model": "anvilcraft:block/fish_tank_outlet", + "y": 0 + } + }, + { + "when": { + "outlet": "true", + "facing": "east" + }, + "apply": { + "model": "anvilcraft:block/fish_tank_outlet", + "y": 90 + } + }, + { + "when": { + "outlet": "true", + "facing": "south" + }, + "apply": { + "model": "anvilcraft:block/fish_tank_outlet", + "y": 180 + } + }, + { + "when": { + "outlet": "true", + "facing": "west" + }, + "apply": { + "model": "anvilcraft:block/fish_tank_outlet", + "y": 270 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft/blockstates/fluid_tank.json b/src/main/resources/assets/anvilcraft/blockstates/fluid_tank.json new file mode 100644 index 0000000000..ca11bd270e --- /dev/null +++ b/src/main/resources/assets/anvilcraft/blockstates/fluid_tank.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "anvilcraft:block/fluid_tank" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft/blockstates/large_fluid_tank.json b/src/main/resources/assets/anvilcraft/blockstates/large_fluid_tank.json new file mode 100644 index 0000000000..c8f34e7106 --- /dev/null +++ b/src/main/resources/assets/anvilcraft/blockstates/large_fluid_tank.json @@ -0,0 +1,85 @@ +{ + "variants": { + "half=mid_center": { + "model": "anvilcraft:block/large_fluid_tank" + }, + "half=bottom_center": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_w": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_e": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_n": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_s": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_wn": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_ws": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_en": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=bottom_es": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_w": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_e": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_n": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_s": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_wn": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_ws": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_en": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=mid_es": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_center": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_w": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_e": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_n": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_s": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_wn": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_ws": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_en": { + "model": "anvilcraft:block/large_fluid_tank_part" + }, + "half=top_es": { + "model": "anvilcraft:block/large_fluid_tank_part" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft/models/block/fish_tank.json b/src/main/resources/assets/anvilcraft/models/block/fish_tank.json index cb2edf3f03..4b1530267c 100644 --- a/src/main/resources/assets/anvilcraft/models/block/fish_tank.json +++ b/src/main/resources/assets/anvilcraft/models/block/fish_tank.json @@ -54,6 +54,17 @@ } ], "display": { + "thirdperson_righthand": { + "rotation": [30, 45, 0], + "scale": [0.6, 0.6, 0.6] + }, + "ground": { + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [30, 45, 0], + "scale": [0.6, 0.6, 0.6] + }, "head": { "rotation": [-180, 0, 0], "scale": [1.125, 1.125, 1.125] diff --git a/src/main/resources/assets/anvilcraft/models/block/fluid_tank.json b/src/main/resources/assets/anvilcraft/models/block/fluid_tank.json index 16d15a495f..70ec2a91d3 100644 --- a/src/main/resources/assets/anvilcraft/models/block/fluid_tank.json +++ b/src/main/resources/assets/anvilcraft/models/block/fluid_tank.json @@ -34,43 +34,5 @@ "down": {"uv": [15, 1, 1, 15], "texture": "#top"} } } - ], - "display": { - "thirdperson_righthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.2, 0.2, 0.2] - }, - "thirdperson_lefthand": { - "rotation": [75, 45, 0], - "translation": [0, 2.5, 0], - "scale": [0.2, 0.2, 0.2] - }, - "firstperson_righthand": { - "rotation": [0, -135, 0], - "translation": [3.75, 0, 0], - "scale": [0.2, 0.2, 0.2] - }, - "firstperson_lefthand": { - "rotation": [0, -135, 0], - "translation": [3.75, 0, 0], - "scale": [0.2, 0.2, 0.2] - }, - "ground": { - "translation": [0, 4, 0], - "scale": [0.2, 0.2, 0.2] - }, - "gui": { - "rotation": [30, -135, 0], - "translation": [0, -0.25, 0], - "scale": [0.24, 0.24, 0.24] - }, - "head": { - "translation": [0, 1, 0], - "scale": [0.6, 0.6, 0.6] - }, - "fixed": { - "scale": [0.66, 0.66, 0.66] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft/models/block/large_fluid_tank_part.json b/src/main/resources/assets/anvilcraft/models/block/large_fluid_tank_part.json new file mode 100644 index 0000000000..4b6d2c61ae --- /dev/null +++ b/src/main/resources/assets/anvilcraft/models/block/large_fluid_tank_part.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/block", + "textures": { + "particle": "anvilcraft:block/large_fluid_tank_side" + } +} \ No newline at end of file