From 2d0d27b743436ba1d1d44008989c58fdc8306f70 Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Fri, 9 Feb 2024 15:12:14 +0000 Subject: [PATCH 1/9] feat: the new blocks but it's not done yet --- gradle.properties | 4 +- .../03e4de26f1265135874f8cdcaebc09d9c08eb42b | 3 + .../1160a324a61ad140c8f8efec97f747ce2b42b9ec | 4 + .../67cce32b1c3cbbcb1f646605f4914e3f196986c2 | 5 + .../75bcd4dba6ca7d365462b0ec45e291d1056349c4 | 3 + .../79b05178e4fcdf2c5a9a3d711df7e12b0a8ae01b | 5 + .../9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e | 23 ++ .../a8d609cf004ffa48275df28c1350f4d44e1c7d32 | 12 + .../c622617f6fabf890a00b9275cd5f643584a8a2c8 | 2 + .../ca20033d77a52b2eda61a478c7fbca106d18e64c | 1 + .../resources/assets/ftbsba/lang/en_us.json | 4 + .../forge/tags/blocks/needs_wood_tool.json | 2 +- .../data/ftbsba/tags/blocks/auto_hammers.json | 2 +- .../dev/ftb/ftbsba/tools/ToolsClient.java | 6 + .../java/dev/ftb/ftbsba/tools/ToolsData.java | 5 + .../dev/ftb/ftbsba/tools/ToolsRegistry.java | 25 ++- .../content/fusion/FusingMachineBlock.java | 46 ++++ .../fusion/FusingMachineBlockEntity.java | 36 +++ .../fusion/FusingMachineContainer.java | 55 +++++ .../content/fusion/FusingMachineScreen.java | 37 ++++ .../content/supercooler/SuperCoolerBlock.java | 46 ++++ .../supercooler/SuperCoolerBlockEntity.java | 208 ++++++++++++++++++ .../supercooler/SuperCoolerContainer.java | 85 +++++++ .../supercooler/SuperCoolerScreen.java | 84 +++++++ .../tools/integration/jei/JEIPlugin.java | 1 - .../ftbsba/tools/utils/IOStackWrapper.java | 54 +++++ .../gui/fusing_machine_background.aseprite | Bin 0 -> 2030 bytes .../gui/fusing_machine_background.png | Bin 0 -> 1371 bytes .../gui/super_cooler_background.aseprite | Bin 0 -> 2032 bytes .../textures/gui/super_cooler_background.png | Bin 0 -> 1537 bytes 30 files changed, 752 insertions(+), 6 deletions(-) create mode 100644 src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b create mode 100644 src/generated/resources/.cache/1160a324a61ad140c8f8efec97f747ce2b42b9ec create mode 100644 src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 create mode 100644 src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 create mode 100644 src/generated/resources/.cache/79b05178e4fcdf2c5a9a3d711df7e12b0a8ae01b create mode 100644 src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e create mode 100644 src/generated/resources/.cache/a8d609cf004ffa48275df28c1350f4d44e1c7d32 create mode 100644 src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 create mode 100644 src/generated/resources/.cache/ca20033d77a52b2eda61a478c7fbca106d18e64c create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java create mode 100644 src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite create mode 100644 src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.png create mode 100644 src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.aseprite create mode 100644 src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png diff --git a/gradle.properties b/gradle.properties index fffac22..53bd0bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G loom.platform=forge minecraft_version=1.19.2 -forge_version=1.19.2-43.2.6 +forge_version=1.19.2-43.3.7 mod_version=1.1.0 maven_group=dev.ftb.mods @@ -10,7 +10,7 @@ archives_base_name=ftb-skyblock-addons mod_id=ftbsba mod_author=FTB Team -jei_version=11.6.0.1016 +jei_version=11.6.0.1018 rhino_version=1902.2.2-build.264 kubejs_version=1902.6.1-build.337 jade_version=4375714 diff --git a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b new file mode 100644 index 0000000..37453f0 --- /dev/null +++ b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b @@ -0,0 +1,3 @@ +// 1.19.2 2024-02-07T15:29:25.340982 Tags for minecraft:item +fb8208eabf5b52787d17b10f56e91b3e1271e4d6 data/ftbsba/tags/items/crooks.json +789251c96a2a2f469b885b225673d95423f634da data/ftbsba/tags/items/hammers.json diff --git a/src/generated/resources/.cache/1160a324a61ad140c8f8efec97f747ce2b42b9ec b/src/generated/resources/.cache/1160a324a61ad140c8f8efec97f747ce2b42b9ec new file mode 100644 index 0000000..aeeab88 --- /dev/null +++ b/src/generated/resources/.cache/1160a324a61ad140c8f8efec97f747ce2b42b9ec @@ -0,0 +1,4 @@ +// 1.19.2 2024-02-07T15:29:25.34058 Global Loot Modifiers : ftbsba +3654bb09969b06cc29a8322f1b2cc7416595ea6f data/forge/loot_modifiers/global_loot_modifiers.json +fc28af48c265f03a878222d6b65a7ac3718e31dd data/ftbsba/loot_modifiers/crook_loot_modifier.json +92c99d7dd9b113ed4bcd78a3ecf89a42560e38af data/ftbsba/loot_modifiers/hammer_loot_modifier.json diff --git a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 new file mode 100644 index 0000000..b62ee1f --- /dev/null +++ b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 @@ -0,0 +1,5 @@ +// 1.19.2 2024-02-07T15:29:25.340708 LootTables +948f46db810742aa1f7a45ae4e85f496eef43dc5 data/ftbsba/loot_tables/blocks/diamond_auto_hammer.json +2ee44a638c38aa0d31cdf3a43e6c6040ec920072 data/ftbsba/loot_tables/blocks/gold_auto_hammer.json +37d636b97fda22b1184b90a1908464d23aaac528 data/ftbsba/loot_tables/blocks/iron_auto_hammer.json +fab496672f8e1dff5dc8c4219be5758a0dce3038 data/ftbsba/loot_tables/blocks/netherite_auto_hammer.json diff --git a/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 b/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 new file mode 100644 index 0000000..6c21d84 --- /dev/null +++ b/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 @@ -0,0 +1,3 @@ +// 1.19.2 2024-02-07T15:29:25.340447 Tags for minecraft:block +112b6aaeec7fa81d44ac017f70ffe88b198a7038 data/forge/tags/blocks/needs_wood_tool.json +112b6aaeec7fa81d44ac017f70ffe88b198a7038 data/ftbsba/tags/blocks/auto_hammers.json diff --git a/src/generated/resources/.cache/79b05178e4fcdf2c5a9a3d711df7e12b0a8ae01b b/src/generated/resources/.cache/79b05178e4fcdf2c5a9a3d711df7e12b0a8ae01b new file mode 100644 index 0000000..e1d1004 --- /dev/null +++ b/src/generated/resources/.cache/79b05178e4fcdf2c5a9a3d711df7e12b0a8ae01b @@ -0,0 +1,5 @@ +// 1.19.2 2024-02-07T15:29:25.340286 Block States: ftbsba +44c77f4f45b3c162963b1bd55ce3364532392b36 assets/ftbsba/blockstates/diamond_auto_hammer.json +feea77a065b8559d6347fc4af26dc563a0490db3 assets/ftbsba/blockstates/gold_auto_hammer.json +33a2acda3b0348e90200100f2e9f28ad8ba3de3d assets/ftbsba/blockstates/iron_auto_hammer.json +654e5f2f61b4cdd8aa679a11dda333a24218339d assets/ftbsba/blockstates/netherite_auto_hammer.json diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e new file mode 100644 index 0000000..c7f6654 --- /dev/null +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -0,0 +1,23 @@ +// 1.19.2 2024-02-07T15:29:25.339159 Recipes +76caa2ffac9a8b3c153057c82b74fd00c5758d19 data/ftbsba/advancements/recipes/ftbsba/diamond_auto_hammer.json +971b5dab8914993196c1d2ece64d640d48db0e39 data/ftbsba/advancements/recipes/ftbsba/diamond_hammer.json +915983f8fed15ad3ad05cd5689c2233aeda39a72 data/ftbsba/advancements/recipes/ftbsba/gold_auto_hammer.json +de8ae2c914315e5680ebf93afd91bc2ce8c0b041 data/ftbsba/advancements/recipes/ftbsba/gold_hammer.json +9531164e2f8cfebabd9514ad1c0b61556e5ac07b data/ftbsba/advancements/recipes/ftbsba/iron_auto_hammer.json +f43ea1c89cd5e9f370d3fa2e825a5b47fbe35dc5 data/ftbsba/advancements/recipes/ftbsba/iron_hammer.json +526b18110a27e8946f10144db8db9a3dbd9d83b5 data/ftbsba/advancements/recipes/ftbsba/netherite_auto_hammer.json +5097506d55ed58376d911ab2e2a94a5d7a13b907 data/ftbsba/advancements/recipes/ftbsba/netherite_hammer.json +ae2b5a84f5310858eb017c0ad368244851bafa4d data/ftbsba/advancements/recipes/ftbsba/stone_crook.json +a3b4f783c559ab57fe31299071c6b04f9ce78c94 data/ftbsba/advancements/recipes/ftbsba/stone_hammer.json +40dddc21150cbc4ecdbcbdefdf85fc678983129d data/ftbsba/advancements/recipes/ftbsba/stone_rod.json +bbb89baa3aef2cef0f5421004afde1eb3aaf3861 data/ftbsba/recipes/diamond_auto_hammer.json +bf0031132f35f16e142deeac2b78bcd518f6d346 data/ftbsba/recipes/diamond_hammer.json +1486bf914fcb03d3f8ab924e7de13ea69f20a69c data/ftbsba/recipes/gold_auto_hammer.json +29143e46f519864a51a06101b0423156cb68b375 data/ftbsba/recipes/gold_hammer.json +1d44891d64f5149c56a59571eb72d3fb06bf8b11 data/ftbsba/recipes/iron_auto_hammer.json +79efc25c8a2ff4ef2c0c913838f8f095942e6a50 data/ftbsba/recipes/iron_hammer.json +15c483e692e0233b8142ad5ba8f0dd356505bdee data/ftbsba/recipes/netherite_auto_hammer.json +ce3f056848f1f83a0f6385377987ea9570cd3f99 data/ftbsba/recipes/netherite_hammer.json +7ee8da43c28168eb841444b40a0e8430b55ca8f6 data/ftbsba/recipes/stone_crook.json +f06156e5586d87d4557422de469325295e99d486 data/ftbsba/recipes/stone_hammer.json +eb65be093f0057752cf295ecf94d65dd7b920c53 data/ftbsba/recipes/stone_rod.json diff --git a/src/generated/resources/.cache/a8d609cf004ffa48275df28c1350f4d44e1c7d32 b/src/generated/resources/.cache/a8d609cf004ffa48275df28c1350f4d44e1c7d32 new file mode 100644 index 0000000..bd73c5b --- /dev/null +++ b/src/generated/resources/.cache/a8d609cf004ffa48275df28c1350f4d44e1c7d32 @@ -0,0 +1,12 @@ +// 1.19.2 2024-02-07T15:29:25.341208 Item Models: ftbsba +06c7c8158d6cd780f5273a97dd4b69fb083a2779 assets/ftbsba/models/item/diamond_auto_hammer.json +0752980420170342016b03131d7710d3dca27224 assets/ftbsba/models/item/diamond_hammer.json +593e27db03393ccc9808c1fbf9af35e50fb2df7c assets/ftbsba/models/item/gold_auto_hammer.json +b84b9a7641dd73f858a5b9513f045b5e1d4da608 assets/ftbsba/models/item/gold_hammer.json +7c64504a98a9a9194f214d8155472d89c058b890 assets/ftbsba/models/item/iron_auto_hammer.json +d818091813bb988f644ad4b908cfc8a9cbd4c076 assets/ftbsba/models/item/iron_hammer.json +95a13a5207334f3b07f31a342312c3b1b2fae48e assets/ftbsba/models/item/netherite_auto_hammer.json +ce663f8ec723fb9d0809b3f683bcba34f5a912a9 assets/ftbsba/models/item/netherite_hammer.json +506b5898f59fec2f3bdf6af88fb21e56f9e5a2a8 assets/ftbsba/models/item/stone_crook.json +f7890e53e26f8b84760d3469c9a6533bbf2e166a assets/ftbsba/models/item/stone_hammer.json +6336e7a46d2bee2475135edc21f7cb0d5bb155f6 assets/ftbsba/models/item/stone_rod.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 new file mode 100644 index 0000000..afe393a --- /dev/null +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -0,0 +1,2 @@ +// 1.19.2 2024-02-07T15:29:25.340844 Languages: en_us +41b86f772260d58aaff5a5c0428ce68db1a3d41e assets/ftbsba/lang/en_us.json diff --git a/src/generated/resources/.cache/ca20033d77a52b2eda61a478c7fbca106d18e64c b/src/generated/resources/.cache/ca20033d77a52b2eda61a478c7fbca106d18e64c new file mode 100644 index 0000000..68be527 --- /dev/null +++ b/src/generated/resources/.cache/ca20033d77a52b2eda61a478c7fbca106d18e64c @@ -0,0 +1 @@ +// 1.19.2 2024-02-07T15:29:25.341567 Block Models: ftbsba diff --git a/src/generated/resources/assets/ftbsba/lang/en_us.json b/src/generated/resources/assets/ftbsba/lang/en_us.json index 745c341..8f793e3 100644 --- a/src/generated/resources/assets/ftbsba/lang/en_us.json +++ b/src/generated/resources/assets/ftbsba/lang/en_us.json @@ -4,13 +4,17 @@ "block.ftbsba.iron_auto_hammer": "Iron Auto-hammer", "block.ftbsba.netherite_auto_hammer": "Netherite Auto-hammer", "config.jade.plugin_ftbsba.blocks": "FTB Skyblock Addons Blocks", + "container.ftbsba.fusing_machine": "Fusing Machine", + "container.ftbsba.super_cooler": "Super Cooler", "ftbsba.jade.buffer": "Buffer", "ftbsba.jade.input": "Input", "ftbsba.jade.processing": "Processing: %s/%s", "ftbsba.jade.waiting": "Waiting for input: %s ticks", "ftbsba.tooltip.auto-hammers": "Automatically crushes materials down using the hammer based on the tier of hammer", "ftbsba.tooltip.fireplow": "Hold right click whilst looking at Stone to create lava", + "ftbsba.tooltip.fusing_machine": "Used to fuse items together to produce new results", "ftbsba.tooltip.hammers": "Crushes materials down to their core components", + "ftbsba.tooltip.super_cooler": "Used to super-cool items to produce new results", "item.ftbsba.diamond_hammer": "Diamond Hammer", "item.ftbsba.gold_hammer": "Gold Hammer", "item.ftbsba.iron_hammer": "Iron Hammer", diff --git a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json index 0953fb1..b55e555 100644 --- a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json +++ b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:diamond_auto_hammer", "ftbsba:iron_auto_hammer", "ftbsba:gold_auto_hammer", + "ftbsba:diamond_auto_hammer", "ftbsba:netherite_auto_hammer" ] } \ No newline at end of file diff --git a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json index 0953fb1..b55e555 100644 --- a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json +++ b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:diamond_auto_hammer", "ftbsba:iron_auto_hammer", "ftbsba:gold_auto_hammer", + "ftbsba:diamond_auto_hammer", "ftbsba:netherite_auto_hammer" ] } \ No newline at end of file diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java index bbbe5ff..78faa21 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java @@ -1,5 +1,8 @@ package dev.ftb.ftbsba.tools; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineScreen; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerScreen; +import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; @@ -9,5 +12,8 @@ public static void init() { ItemBlockRenderTypes.setRenderLayer(ToolsRegistry.GOLD_AUTO_HAMMER.get(), RenderType.cutout()); ItemBlockRenderTypes.setRenderLayer(ToolsRegistry.DIAMOND_AUTO_HAMMER.get(), RenderType.cutout()); ItemBlockRenderTypes.setRenderLayer(ToolsRegistry.NETHERITE_AUTO_HAMMER.get(), RenderType.cutout()); + + MenuScreens.register(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), FusingMachineScreen::new); + MenuScreens.register(ToolsRegistry.SUPER_COOLER_CONTAINER.get(), SuperCoolerScreen::new); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java index d493862..ab0e26a 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java @@ -125,12 +125,17 @@ protected void addTranslations() { this.add("ftbsba.tooltip.hammers", "Crushes materials down to their core components"); this.add("ftbsba.tooltip.auto-hammers", "Automatically crushes materials down using the hammer based on the tier of hammer"); + this.add("ftbsba.tooltip.fusing_machine", "Used to fuse items together to produce new results"); + this.add("ftbsba.tooltip.super_cooler", "Used to super-cool items to produce new results"); + this.add("ftbsba.jade.waiting", "Waiting for input: %s ticks"); this.add("ftbsba.jade.processing", "Processing: %s/%s"); this.add("ftbsba.jade.input", "Input"); this.add("ftbsba.jade.buffer", "Buffer"); this.add("config.jade.plugin_ftbsba.blocks", "FTB Skyblock Addons Blocks"); + this.add("container.ftbsba.super_cooler", "Super Cooler"); + this.add("container.ftbsba.fusing_machine", "Fusing Machine"); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java index 2de5f1a..f9fdc6b 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java @@ -7,6 +7,12 @@ import dev.ftb.ftbsba.tools.content.autohammer.AutoHammerBlock; import dev.ftb.ftbsba.tools.content.autohammer.AutoHammerBlockEntity; import dev.ftb.ftbsba.tools.content.autohammer.AutoHammerProperties; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineBlock; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineBlockEntity; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineContainer; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerBlock; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerBlockEntity; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerContainer; import dev.ftb.ftbsba.tools.loot.CrookModifier; import dev.ftb.ftbsba.tools.loot.HammerModifier; import dev.ftb.ftbsba.tools.recipies.CrookRecipe; @@ -16,6 +22,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; +import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.*; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; @@ -24,6 +31,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.extensions.IForgeMenuType; import net.minecraftforge.common.loot.IGlobalLootModifier; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @@ -48,6 +56,7 @@ public interface ToolsRegistry { DeferredRegister> LOOT_MODIFIERS_REGISTRY = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, FTBSBA.MOD_ID); DeferredRegister> RECIPE_SERIALIZER_REGISTRY = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, FTBSBA.MOD_ID); DeferredRegister> RECIPE_TYPE_REGISTRY = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, FTBSBA.MOD_ID); + DeferredRegister> CONTAINER_REGISTRY = DeferredRegister.create(ForgeRegistries.MENU_TYPES, FTBSBA.MOD_ID); // All the registries :D List> REGISTERS = List.of( @@ -56,7 +65,8 @@ public interface ToolsRegistry { BLOCK_ENTITY_REGISTRY, LOOT_MODIFIERS_REGISTRY, RECIPE_SERIALIZER_REGISTRY, - RECIPE_TYPE_REGISTRY + RECIPE_TYPE_REGISTRY, + CONTAINER_REGISTRY ); // Hammers @@ -75,16 +85,29 @@ public interface ToolsRegistry { RegistryObject DIAMOND_AUTO_HAMMER = BLOCK_REGISTRY.register("diamond_auto_hammer", () -> new AutoHammerBlock(DIAMOND_HAMMER, AutoHammerProperties.DIAMOND)); RegistryObject NETHERITE_AUTO_HAMMER = BLOCK_REGISTRY.register("netherite_auto_hammer", () -> new AutoHammerBlock(NETHERITE_HAMMER, AutoHammerProperties.NETHERITE)); + RegistryObject FUSING_MACHINE = BLOCK_REGISTRY.register("fusing_machine", FusingMachineBlock::new); + RegistryObject SUPER_COOLER = BLOCK_REGISTRY.register("super_cooler", SuperCoolerBlock::new); + RegistryObject IRON_AUTO_HAMMER_BLOCK_ITEM = ITEM_REGISTRY.register("iron_auto_hammer", () -> new ToolTipBlockItem(IRON_AUTO_HAMMER.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.auto-hammers").withStyle(ChatFormatting.GRAY))); RegistryObject GOLD_AUTO_HAMMER_BLOCK_ITEM = ITEM_REGISTRY.register("gold_auto_hammer", () -> new ToolTipBlockItem(GOLD_AUTO_HAMMER.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.auto-hammers").withStyle(ChatFormatting.GRAY))); RegistryObject DIAMOND_AUTO_HAMMER_BLOCK_ITEM = ITEM_REGISTRY.register("diamond_auto_hammer", () -> new ToolTipBlockItem(DIAMOND_AUTO_HAMMER.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.auto-hammers").withStyle(ChatFormatting.GRAY))); RegistryObject NETHERITE_AUTO_HAMMER_BLOCK_ITEM = ITEM_REGISTRY.register("netherite_auto_hammer", () -> new ToolTipBlockItem(NETHERITE_AUTO_HAMMER.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.auto-hammers").withStyle(ChatFormatting.GRAY))); + RegistryObject FUSING_MACHINE_BLOCK_ITEM = ITEM_REGISTRY.register("fusing_machine", () -> new ToolTipBlockItem(FUSING_MACHINE.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.fusing_machine").withStyle(ChatFormatting.GRAY))); + RegistryObject SUPER_COOLER_BLOCK_ITEM = ITEM_REGISTRY.register("super_cooler", () -> new ToolTipBlockItem(SUPER_COOLER.get(), new Item.Properties().tab(CREATIVE_GROUP), Component.translatable("ftbsba.tooltip.super_cooler").withStyle(ChatFormatting.GRAY))); + + RegistryObject> FUSING_MACHINE_CONTAINER = CONTAINER_REGISTRY.register("fusing_machine", () -> IForgeMenuType.create(FusingMachineContainer::new)); + RegistryObject> SUPER_COOLER_CONTAINER = CONTAINER_REGISTRY.register("super_cooler", () -> IForgeMenuType.create(SuperCoolerContainer::new)); + RegistryObject> IRON_AUTO_HAMMER_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("iron_auto_hammer", () -> BlockEntityType.Builder.of(AutoHammerBlockEntity.Iron::new, IRON_AUTO_HAMMER.get()).build(null)); RegistryObject> GOLD_AUTO_HAMMER_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("gold_auto_hammer", () -> BlockEntityType.Builder.of(AutoHammerBlockEntity.Gold::new, GOLD_AUTO_HAMMER.get()).build(null)); RegistryObject> DIAMOND_AUTO_HAMMER_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("diamond_auto_hammer", () -> BlockEntityType.Builder.of(AutoHammerBlockEntity.Diamond::new, DIAMOND_AUTO_HAMMER.get()).build(null)); RegistryObject> NETHERITE_AUTO_HAMMER_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("netherite_auto_hammer", () -> BlockEntityType.Builder.of(AutoHammerBlockEntity.Netherite::new, NETHERITE_AUTO_HAMMER.get()).build(null)); + RegistryObject> FUSING_MACHINE_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("fusing_machine", () -> BlockEntityType.Builder.of(FusingMachineBlockEntity::new, FUSING_MACHINE.get()).build(null)); + RegistryObject> SUPER_COOLER_BLOCK_ENTITY = BLOCK_ENTITY_REGISTRY.register("super_cooler", () -> BlockEntityType.Builder.of(SuperCoolerBlockEntity::new, SUPER_COOLER.get()).build(null)); + + RegistryObject> HAMMER_LOOT_MODIFIER = LOOT_MODIFIERS_REGISTRY.register("hammer_loot_modifier", () -> HammerModifier.CODEC); RegistryObject> CROOK_LOOT_MODIFIER = LOOT_MODIFIERS_REGISTRY.register("crook_loot_modifier", () -> CrookModifier.CODEC); diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java new file mode 100644 index 0000000..6daee99 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java @@ -0,0 +1,46 @@ +package dev.ftb.ftbsba.tools.content.fusion; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +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.material.Material; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.Nullable; + +public class FusingMachineBlock extends Block implements EntityBlock { + public FusingMachineBlock() { + super(Properties.of(Material.STONE).strength(1F, 1F)); + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } + + NetworkHooks.openScreen((ServerPlayer) player, (FusingMachineBlockEntity) level.getBlockEntity(pos)); + return InteractionResult.SUCCESS; + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new FusingMachineBlockEntity(pos, state); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { + return FusingMachineBlockEntity::ticker; + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java new file mode 100644 index 0000000..e93f5b5 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java @@ -0,0 +1,36 @@ +package dev.ftb.ftbsba.tools.content.fusion; + +import dev.ftb.ftbsba.tools.ToolsRegistry; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +public class FusingMachineBlockEntity extends BlockEntity implements MenuProvider { + public FusingMachineBlockEntity(BlockPos pos, BlockState state) { + super(ToolsRegistry.FUSING_MACHINE_BLOCK_ENTITY.get(), pos, state); + } + + public static void ticker(Level level, BlockPos pos, BlockState state, T t) { + if (t instanceof FusingMachineBlockEntity entity) { +// System.out.println("FusingMachineBlockEntity.ticker"); + } + } + + @Override + public Component getDisplayName() { + return Component.translatable("container.ftbsba.fusing_machine"); // TODO: Add translation + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { + return new FusingMachineContainer(i, arg, arg2); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java new file mode 100644 index 0000000..461a7b9 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java @@ -0,0 +1,55 @@ +package dev.ftb.ftbsba.tools.content.fusion; + +import dev.ftb.ftbsba.tools.ToolsRegistry; +import net.minecraft.client.gui.screens.inventory.ContainerScreen; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public class FusingMachineContainer extends AbstractContainerMenu { + protected FusingMachineContainer(int i, Inventory arg, Player arg2) { + super(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), i); + + addPlayerSlots(arg, 8, 56, this::addSlot); + + } + + public FusingMachineContainer(int i, Inventory arg, FriendlyByteBuf arg2) { + this(i, arg, arg.player); + } + + @Override + public ItemStack quickMoveStack(Player arg, int i) { + return null; + } + + @Override + public boolean stillValid(Player arg) { + return true; + } + + public static void addPlayerSlots(Inventory playerInventory, int inX, int inY, Consumer addSlot) { + // Slots for the hotbar + for (int row = 0; row < 9; ++ row) { + int x = inX + row * 18; + int y = inY + 86; + addSlot.accept(new Slot(playerInventory, row, x, y)); + } + // Slots for the main inventory + for (int row = 1; row < 4; ++ row) { + for (int col = 0; col < 9; ++ col) { + int x = inX + col * 18; + int y = row * 18 + (inY + 10); + addSlot.accept(new Slot(playerInventory, col + row * 9, x, y)); + } + } + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java new file mode 100644 index 0000000..4aa2816 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java @@ -0,0 +1,37 @@ +package dev.ftb.ftbsba.tools.content.fusion; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.ftb.ftbsba.FTBSBA; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; + +public class FusingMachineScreen extends AbstractContainerScreen { + private static final ResourceLocation TEXTURE = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/fusing_machine_background.png"); + + public FusingMachineScreen(FusingMachineContainer arg, Inventory arg2, Component arg3) { + super(arg, arg2, arg3); + } + + @Override + protected void init() { + super.init(); + } + + @Override + public void render(PoseStack arg, int m, int n, float g) { + super.render(arg, m, n, g); + } + + @Override + protected void renderBg(PoseStack arg, float f, int i, int j) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, TEXTURE); + + this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java new file mode 100644 index 0000000..7f2c91c --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java @@ -0,0 +1,46 @@ +package dev.ftb.ftbsba.tools.content.supercooler; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +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.material.Material; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.Nullable; + +public class SuperCoolerBlock extends Block implements EntityBlock { + public SuperCoolerBlock() { + super(Properties.of(Material.STONE).strength(1F, 1F)); + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } + + NetworkHooks.openScreen((ServerPlayer) player, (SuperCoolerBlockEntity) level.getBlockEntity(pos), pos); + return InteractionResult.SUCCESS; + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new SuperCoolerBlockEntity(pos, state); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { + return SuperCoolerBlockEntity::ticker; + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java new file mode 100644 index 0000000..cfd306d --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -0,0 +1,208 @@ +package dev.ftb.ftbsba.tools.content.supercooler; + +import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.utils.IOStackWrapper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.energy.EnergyStorage; +import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.templates.FluidTank; +import net.minecraftforge.items.ItemStackHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider { + public ItemStackHandler inventory = new ItemStackHandler(3) { + @Override + protected void onContentsChanged(int slot) { + setChanged(); + } + }; + + public ItemStackHandler output = new ItemStackHandler(1) { + @Override + protected void onContentsChanged(int slot) { + setChanged(); + } + }; + + public LazyOptional energy = LazyOptional.of(() -> new EnergyStorage(100000, 1000, 1000) { + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + var result = super.receiveEnergy(maxReceive, simulate); + if (!simulate) { + setChanged(); + } + return result; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + var result = super.extractEnergy(maxExtract, simulate); + if (!simulate) { + setChanged(); + } + return result; + } + }); + + public LazyOptional tank = LazyOptional.of(() -> new FluidTank(10000) { + @Override + protected void onContentsChanged() { + setChanged(); + } + }); + + public LazyOptional ioWrapper = LazyOptional.of(() -> new IOStackWrapper(inventory, output)); + + ContainerData containerData = new ContainerData() { + @Override + public int get(int index) { + // Send energy and fluid levels to client + int energyStored = energy.map(IEnergyStorage::getEnergyStored).orElse(0); + + // Compact energy into two shorts + var compactedEnergyPartOne = energyStored & 0xFFFF; + var compactedEnergyPartTwo = (energyStored >> 16) & 0xFFFF; + + System.out.println("compactedEnergyPartOne: " + compactedEnergyPartOne); + System.out.println("compactedEnergyPartTwo: " + compactedEnergyPartTwo); + System.out.println("Original energyStored: " + energyStored); + + + + return switch (index) { + case 0 -> compactedEnergyPartOne; + case 1 -> compactedEnergyPartTwo; + case 2 -> tank.map(IFluidTank::getFluidAmount).orElse(0); + default -> 0; + }; + } + + @Override + public void set(int index, int value) { + // No-op + } + + @Override + public int getCount() { + return 3; + } + }; + + public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { + super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) { + return ioWrapper.cast(); + } else if (cap == ForgeCapabilities.ENERGY) { + return energy.cast(); + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + return tank.cast(); + } + + return super.getCapability(cap, side); + } + + public static void ticker(Level level, BlockPos pos, BlockState state, T t) { + if (t instanceof SuperCoolerBlockEntity entity) { +// System.out.println("SuperCoolerBlockEntity.ticker"); + } + } + + @Override + public Component getDisplayName() { + return Component.translatable("container.ftbsba.super_cooler"); // TODO: Add translation + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { + return new SuperCoolerContainer(i, containerData, arg, arg2, this); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + ioWrapper.invalidate(); + energy.invalidate(); + tank.invalidate(); + } + + @Override + public void load(CompoundTag arg) { + super.load(arg); + + ioWrapper.ifPresent(wrapper -> { + wrapper.getInput().deserializeNBT(arg.getCompound("input")); + wrapper.getInput().deserializeNBT(arg.getCompound("output")); + }); + energy.ifPresent(storage -> + storage.receiveEnergy(arg.getInt("energy"), false) + ); + tank.ifPresent(tank -> { + var tag = arg.getCompound("fluid"); + tank.fill(FluidStack.loadFluidStackFromNBT(tag), IFluidHandler.FluidAction.EXECUTE); + }); + } + + @Override + protected void saveAdditional(CompoundTag arg) { + super.saveAdditional(arg); + + ioWrapper.ifPresent(wrapper -> { + arg.put("input", wrapper.getInput().serializeNBT()); + arg.put("output", wrapper.getInput().serializeNBT()); + }); + energy.ifPresent(storage -> arg.putInt("energy", storage.getEnergyStored())); + tank.ifPresent(tank -> { + var tag = new CompoundTag(); + tank.getFluid().writeToNBT(tag); + arg.put("fluid", tag); + }); + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this, entity -> this.getUpdateTag()); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag compoundTag = new CompoundTag(); + saveAdditional(compoundTag); + return compoundTag; + } + + + @Override + public void handleUpdateTag(CompoundTag tag) { + load(tag); + } + + @Override + public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { + load(pkt.getTag()); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java new file mode 100644 index 0000000..a87bc65 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java @@ -0,0 +1,85 @@ +package dev.ftb.ftbsba.tools.content.supercooler; + +import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineContainer; +import net.minecraft.core.Vec3i; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class SuperCoolerContainer extends AbstractContainerMenu { + SuperCoolerBlockEntity entity; + ContainerData containerData; + + protected SuperCoolerContainer(int i, ContainerData containerData, Inventory arg, Player arg2, SuperCoolerBlockEntity entity) { + super(ToolsRegistry.SUPER_COOLER_CONTAINER.get(), i); + FusingMachineContainer.addPlayerSlots(arg, 8, 56, this::addSlot); + + this.entity = entity; + this.entity.ioWrapper.ifPresent(inventory -> { + int startY = 10; + addSlot(new SlotItemHandler(inventory.getInput(), 0, 42, startY)); + addSlot(new SlotItemHandler(inventory.getInput(), 1, 42, startY + 18)); + addSlot(new SlotItemHandler(inventory.getInput(), 2, 42, startY + (18 * 2))); + addSlot(new SlotItemHandler(inventory.getOutput(), 0, 122, startY + 19)); + }); + + this.containerData = containerData; + addDataSlots(containerData); + } + + public SuperCoolerContainer(int i, Inventory arg, FriendlyByteBuf arg2) { + this(i, arg, arg.player, (SuperCoolerBlockEntity) arg.player.level.getBlockEntity(arg2.readBlockPos())); + } + + public SuperCoolerContainer(int i, Inventory arg, Player player, SuperCoolerBlockEntity entity) { + this(i, entity.containerData, arg, player, entity); + } + + @Override + public ItemStack quickMoveStack(Player arg, int index) { + ItemStack itemstack = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack currentStack = slot.getItem(); + itemstack = currentStack.copy(); + + if (index < 3) { + if (!this.moveItemStackTo(currentStack, 3, this.slots.size(), false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(currentStack, 0, 3, false)) { + return ItemStack.EMPTY; + } + + if (currentStack.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + + return itemstack; + } + + @Override + public boolean stillValid(Player arg) { + Vec3 position = arg.position(); + return this.entity.getBlockPos().distManhattan(new Vec3i(position.x, position.y, position.z)) <= 8; + } + + @Override + public void slotsChanged(Container arg) { + super.slotsChanged(arg); + this.entity.setChanged(); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java new file mode 100644 index 0000000..d998fa7 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java @@ -0,0 +1,84 @@ +package dev.ftb.ftbsba.tools.content.supercooler; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.ftb.ftbsba.FTBSBA; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.fluids.IFluidTank; + +public class SuperCoolerScreen extends AbstractContainerScreen { + private static final ResourceLocation TEXTURE = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/super_cooler_background.png"); + + public SuperCoolerScreen(SuperCoolerContainer arg, Inventory arg2, Component arg3) { + super(arg, arg2, arg3); + this.titleLabelX = 96; + + } + + @Override + public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { + super.render(arg, mouseX, mouseY, partialTicks); + + var data = this.menu.entity.containerData; + if (mouseX > this.leftPos + 3 && mouseX < this.leftPos + 21 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { + arg.pushPose(); + arg.translate(mouseX - 5, mouseY, 0); + arg.scale(0.6F, 0.6F, 0F); + this.renderTooltip(arg, Component.literal(data.get(2) + " / " + this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0) + " mB"), 0, 0); + arg.popPose(); + } + + if (mouseX > this.leftPos + 166 && mouseX < this.leftPos + 174 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { + var uncompressedEnergy = (data.get(0) & 0xFFFF) | (data.get(1) << 16); + +// System.out.println(data.get(0) + " " + data.get(1) + " " + uncompressedEnergy); + + MutableComponent energyText = Component.literal(uncompressedEnergy + " / " + this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0) + " FE"); + int width = this.font.width(energyText); + int scaledWidth = (int) (width * 0.6F); + arg.pushPose(); + arg.translate(mouseX - 10 - scaledWidth, mouseY, 0); + arg.scale(0.6F, 0.6F, 0F); + this.renderTooltip(arg, energyText, 0, 0); + arg.popPose(); + } + } + + @Override + protected void renderBg(PoseStack arg, float f, int i, int j) { + renderBackground(arg); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, TEXTURE); + + this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); + this.blit(arg, this.leftPos + 4, this.topPos + 6, 178, 3, 18, 67); + + var data = this.menu.entity.containerData; + + // Energy + int energyHeight = (int) (data.get(0) / (float) data.get(1) * 65); + this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4, 197, 4, 5, energyHeight); + + // Fluid amount + int fluidHeight = (int) (data.get(2) / (float) data.get(3) * 65); + this.blit(arg, this.leftPos + 4, this.topPos + 6 + 65, 178, 71, 18, -fluidHeight); + } + + @Override + protected void renderLabels(PoseStack arg, int i, int j) { + arg.pushPose(); + arg.scale(0.75F, 0.75F, 0.75F); + this.font.draw(arg, this.title, (float)this.titleLabelX, (float)this.titleLabelY, 4210752); + arg.popPose(); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java index 9470cd2..67bed69 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java @@ -2,7 +2,6 @@ import dev.ftb.ftbsba.FTBSBA; import dev.ftb.ftbsba.tools.ToolsRegistry; -import dev.ftb.ftbsba.tools.recipies.CrookRecipe; import dev.ftb.ftbsba.tools.recipies.NoInventory; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; diff --git a/src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java b/src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java new file mode 100644 index 0000000..ae3ab06 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java @@ -0,0 +1,54 @@ +package dev.ftb.ftbsba.tools.utils; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import org.jetbrains.annotations.NotNull; + +public class IOStackWrapper implements IItemHandler { + ItemStackHandler input; + ItemStackHandler output; + + public IOStackWrapper(ItemStackHandler input, ItemStackHandler output) { + this.input = input; + this.output = output; + } + + @Override + public int getSlots() { + return input.getSlots() + output.getSlots(); + } + + @Override + public @NotNull ItemStack getStackInSlot(int i) { + return i < input.getSlots() ? input.getStackInSlot(i) : output.getStackInSlot(i - input.getSlots()); + } + + @Override + public @NotNull ItemStack insertItem(int i, @NotNull ItemStack arg, boolean bl) { + return i < input.getSlots() ? input.insertItem(i, arg, bl) : arg; + } + + @Override + public @NotNull ItemStack extractItem(int i, int j, boolean bl) { + return i < input.getSlots() ? input.extractItem(i, j, bl) : output.extractItem(i - input.getSlots(), j, bl); + } + + @Override + public int getSlotLimit(int i) { + return i < input.getSlots() ? input.getSlotLimit(i) : output.getSlotLimit(i - input.getSlots()); + } + + @Override + public boolean isItemValid(int i, @NotNull ItemStack arg) { + return i < input.getSlots() && input.isItemValid(i, arg); + } + + public ItemStackHandler getInput() { + return input; + } + + public ItemStackHandler getOutput() { + return output; + } +} diff --git a/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite b/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..cdb4266acd605f186a156ba56dea8b02242f58c8 GIT binary patch literal 2030 zcmeHIdrVt(6#lhP80uD#msDnp47wPX4sjNbH~VX$RYagZ%k=3GLglaj#zr>xEqCflIM!^=|3V;5{My}dtA+aVCK@gEca@VmX= zJ^jx4<(%|8xt;JuXy_aVAr9iK0757O?ghvZ$0;Izxc&`fL;tyHzN;%A8ic^@D{{45 z)NTfZFp>PBlCmf>A7TJPot>S)B_$=m>FMdfQmGUe06aT8>yF{8$z+1KEHd)Xth>fD zV?VzQa8@jaQ^S>&9SD7+R6>kHLiWH(gf6%kl<4Sa;K|@%&Ab9nQ2ytC`U_a0(A&9@ zPTRp<@D_{(SHV(Hz)WDU5j=$8uK=&WC~(PXQHXP|0ALGv;*S5Dyc)*x7I`fi&bc)_ zl)U?>GEcZ{($}37#duCX=Q$ngIsLrn^oAZTOeu1YjUj#rc&+4XEceXW>h-8-dtMD` zC5EFeuMWCcRa6}FlJ>H2SJv>Z@TdD8-@A5a=~snSf&wNiYoFw;S3(Q$@Szif!bCMW zqWCf*+UEFi+`oyIw^2evwME7MRu&WV;b&d@N(rHImiVcqSIu6Trb2JbNio9|N0?0v zU(M+3I;;UT``Vn*8kVY+L% z8`BLbn`7Ayzx^2wv3&DJ%5aQ3IHP!bTAq|99%`fvil8nkk92*gj6W z(ZXi39o;)7i8SKi7v*Nzi?0>q7wq>t=(C~t{5F*l=XDwtaTsT^G#!{Qfqx}_9?coZ zage22LvEjeCQ12YJ6tMB;tLy3;?_RX*i_flrlPCy%=wWO15F9xw4U_q&VA%+L)CX% zWM@jc0$K-&*mq7b@7;AI<#SSRN1YleEa$5uRk-<5<8i?!Ti&GPg%7AkTp*zI$!1wb zVc9MABbkF_(#g-GS)1ea!?@+uU+&}4=Gtv5rET<>Aup;5v)05q2^z4HI8oKZ-kfQ| z;f;4Nu~*l+hX_w;t5y#+<1>ovXZ4xGWsY~X786IsNSNHr{`fSa-bT|jzkZCIhv^o+ zE|FFbd`&UJ-wqg$m6^3mL8$S5dEq8pGjYg4EkzC`v>Y%tXmM|VOopFg>*6i7ll}d~ zMSZPZwgiL<-#q(!0jm#^5$&vf6`ODcGqVru{3({YefPM+{OG4qTPxOh{2b|KIgvzN z&^p*&9{dZ{BQLbD%)TfAjXiG)?qfs+!UB%qxi$jIH_EiX7TK~)% ziL1_Q*}BTph_ltt$N!0QAH?x^sP5j%>ta{AH@XII!G#%k=w+CpvO>TM@38$lZxy-8q?;K+f9$pAc6d z{r~^}W5olJnz*mk8vo_6n7KSyfW?~2cg0H+ zU*TO_I`5R1{%2c%X0E_1?zy|zGlF;Dl3O6R$H~7yFNYtKV2(h`1)b$Y=%7> zSFZZStYF8wYSmlDy01G+*XPXou2;$U;G;dmt#4MR-ZFmpJdeM@rSAS`CWgl!xfL9^ z6b#v?uukY;V4A}6Kt{lwfzgYpfUiTjfkBmVPyMop1{W5A1u6{hnICa%;6Bh_xbEY$ z>ueI&cOQxV#&FszXA2)m3^*{UKmS@i^WqZyyw5lIwe8;kX;=x{rAA7jg$oyZ)$i{x))5#Ba82a_6@%=x;(A?j% zZl_osrocI4ov<)kZfCB>~3ej+e!M*z5W8sAv-OHicU?zdM6C@vGoUbpdS1RcPnIFw4 z^H#E8Pil5UbL^Kr{FtV_W$gRLb7T3TlN<^THyN&qF|ht8N0t_~6@vd$@? F2>|*L_A>wg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.aseprite b/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..eddc9d2a208dc84124c55b6f0cb233b1d4d3318d GIT binary patch literal 2032 zcmeHIZA@Eb6n^^!G~uIL1q4(e%;L7pZB}TP(Oq0k$kb5x0~5lJh7B?Y+1Sv{El6K9 zvS?74bV}lYIwxbyC}R>CknQ3qWisJTM|6yjPRdqE#dd28ZEf%CX}b*;vGI?IKYVWQ zb5Eah-kg&@C%3k6gl@KQ5aJ+C1Q0?+a4$lIIDQd{;QBYP5BhuV#00v=K!Z5A!&3q+ zm$Y+$kdUIfr{pfl+z$x=A%npHTvJm6oR^meER)HA0l-eDGZ@2HqtOU)U0T|MY_KLY z6QM8z&ZeisscEfNk5G4UF~lS;ZU>x1=uCh?kw_%K*4Ws_`wBck`JeykFR%cGeE&xJ zZ3lP3TQC+}1xrBzGl9WI@DPH(0=xpFz$L#$asIsmfGyxjF#d1y<1iLKg|}ol|JDf5 zONEDv%afN)h6j@=8$+j`37wXPPCpwuoxyNn%9P;P1mb&u*UF*Bxru_>;~P-+_PeJo zzV`D%?P~tn=lk?k%ts#1D{G?-sh>&pl4DOBu4lavrC=SIul@Yai?drTx~$r(9%Y&I zja%-9(szZL&7+(3rL5TI9c(Y|H7YHt$br4Tb|jdLIr%E zy2IR(JFU6d8LVD-y2zKV%2wE^O70eix^6nT_Ec_Pz8U{W?dOj4u%$Y(Q1AW3t4(vd zT5~|iVfB~utyqamKCib>o61FGkK@{VCWVx=yeLvA|vso3HA5hI^(zdCZTpTsd*amG`RhJarHdDm#cDK3w|jWDmu|L z^qnb!veL7e73?=oR_>f`YM<{pCRX~CZ<@OB+AE3jt;$#Tu!Sm3vlBOZypn64n6W8S zXQfX?HsT+;lXTN{SABlv5GH?oIu&1a+v%q3aS<-_G~nnb zZVt!ELN^OJly^P0-Xf}bG$Un$j)veZOG;Gsu_XBh}822s1 zxr)qY(xjM6u~I=8#dO!X_i!f<#A*aPeZ#hiQIuG^_+7`hslsVW95GUu(o z?KQK^L(m!NuGS09BzJ&OcaV#3;dm>hQ)@`{6y8EdxpFEwovXIhhyENKqt-N>l}`h=uo40#R_q(nDh4b64%RUZ01SFQ-Nac^2PDVg8pcP&TUw;YJH%N zw``sEDB^4rhKU|+IU*Mb(8-CYq4YpG9}U2JaB&6!dJbmL)+Y)c;h``?Dla&y;BU&f T+%VD6#NrRHaM72AqW(VtFWzTZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png b/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png new file mode 100644 index 0000000000000000000000000000000000000000..ed21bff3dedbb478159739955e8fb7862c930a38 GIT binary patch literal 1537 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K(=pyPlzi} z@c;k+$BrHA?(Pl^4K+762a0_C`V~mtzkk19SsBQ{1phfX@2jgnnml=DYU+P6F^B>+ zHMRGmqL_*YkI2cBCzmZ-wt4er8ae4l?8;1_(fK7oe!-w%1pyfS|G(+~Bma|D{r^7) zB0*j9(!$%om}7qK>EaktG3V`_i<1@^h_pOhW7U(t!Rr101=xWM#48zkTi< zRdY^p^Dt~zneJ`QG-pfY7YT-AVc!>C`>veIn7942&Uf*Kia){!?%O5nD%;l@F+6+B z&cJY<;h59~v4)AU4Evs0Zf7(2?_NDej=>^|`3{2wBSXV9h6v_M3=9t54EN8Qa3`=Z zFhns~94dAAwEXL(`8V8cnJ1l(`sL%#@Vw;mKC6Za%mGF28r%z3nIWi z9HE>Foy$!R@HPknQ^Nv{1AB!UzPCB39k4xll=Hw-)(`JQnI+7**D~xV`+I%K%l(-T z*T!CMjkn#k{CT2I6fg4E zU;L53SRs7D5tCc$pO>9wJR{r|t=7GU@vDkn-W|=&d<&w#cBuP4y5CUpXSIQt+|s8e z7Z+~{YA97d%%HIE&QF`m?-Q(;!~EJ7?7#E7-$k71;ZN-emj6~UE)q`on-pPw;P=s6 z53lnS%w;L6$4UwjPjHxcTKY51 z^i}df&VO~=Lm~)8a26MH#qIxz?i!Z3WpCEHujm75h-R#~&Ft5o!~5Wkd;e>=5pc#0 zxdXT540az%1BP^N!)Y-Fy?G1%Rhlsrd|>%{KDg#jH-C8ftVfU6|G4?6m8oG@gB8OH h?iI{KnQ__Xfc?}}zdy(*s_}w?!PC{xWt~$(695i^E?fWr literal 0 HcmV?d00001 From c7e199cd9ce15ec4c9e6a89b106b14b9af09c08a Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Fri, 9 Feb 2024 15:57:05 +0000 Subject: [PATCH 2/9] fix: use correct save and load methods --- .../supercooler/SuperCoolerBlockEntity.java | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index cfd306d..0b38447 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -44,25 +44,7 @@ protected void onContentsChanged(int slot) { } }; - public LazyOptional energy = LazyOptional.of(() -> new EnergyStorage(100000, 1000, 1000) { - @Override - public int receiveEnergy(int maxReceive, boolean simulate) { - var result = super.receiveEnergy(maxReceive, simulate); - if (!simulate) { - setChanged(); - } - return result; - } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) { - var result = super.extractEnergy(maxExtract, simulate); - if (!simulate) { - setChanged(); - } - return result; - } - }); + public LazyOptional energy = LazyOptional.of(() -> new CustomEnergy(this)); public LazyOptional tank = LazyOptional.of(() -> new FluidTank(10000) { @Override @@ -158,12 +140,9 @@ public void load(CompoundTag arg) { wrapper.getInput().deserializeNBT(arg.getCompound("input")); wrapper.getInput().deserializeNBT(arg.getCompound("output")); }); - energy.ifPresent(storage -> - storage.receiveEnergy(arg.getInt("energy"), false) - ); + energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); tank.ifPresent(tank -> { - var tag = arg.getCompound("fluid"); - tank.fill(FluidStack.loadFluidStackFromNBT(tag), IFluidHandler.FluidAction.EXECUTE); + ((FluidTank) tank).readFromNBT(arg.getCompound("fluid")); }); } @@ -175,11 +154,9 @@ protected void saveAdditional(CompoundTag arg) { arg.put("input", wrapper.getInput().serializeNBT()); arg.put("output", wrapper.getInput().serializeNBT()); }); - energy.ifPresent(storage -> arg.putInt("energy", storage.getEnergyStored())); + energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); tank.ifPresent(tank -> { - var tag = new CompoundTag(); - tank.getFluid().writeToNBT(tag); - arg.put("fluid", tag); + arg.put("fluid", ((FluidTank) tank).writeToNBT(new CompoundTag())); }); } @@ -205,4 +182,31 @@ public void handleUpdateTag(CompoundTag tag) { public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { load(pkt.getTag()); } + + public static class CustomEnergy extends EnergyStorage { + BlockEntity entity; + + public CustomEnergy(BlockEntity blockEntity) { + super(100000, 1000, 1000); + entity = blockEntity; + + } + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + var result = super.receiveEnergy(maxReceive, simulate); + if (!simulate) { + this.entity.setChanged(); + } + return result; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + var result = super.extractEnergy(maxExtract, simulate); + if (!simulate) { + this.entity.setChanged(); + } + return result; + } + } } From 6da6017501ad92db6fd86f75fb6df84ba445887b Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Fri, 9 Feb 2024 20:21:01 +0000 Subject: [PATCH 3/9] feat: recipes and kubejs recipes --- .../dev/ftb/ftbsba/tools/ToolsRegistry.java | 18 ++- .../supercooler/SuperCoolerBlockEntity.java | 89 +++++++----- .../supercooler/SuperCoolerScreen.java | 102 ++++++++++++-- .../kubejs/EnergyRecipeComponent.java | 30 ++++ .../kubejs/FusingMachineRecipeSchema.java | 17 +++ .../integration/kubejs/KubeJSIntegration.java | 2 + .../kubejs/SuperCoolerRecipeSchema.java | 20 +++ .../tools/recipies/FusingMachineRecipe.java | 85 ++++++++++++ .../FusingMachineRecipeSerializer.java | 90 ++++++++++++ .../tools/recipies/SuperCoolerRecipe.java | 130 ++++++++++++++++++ .../recipies/SuperCoolerRecipeSerializer.java | 70 ++++++++++ .../gui/fusing_machine_background.png | Bin 1371 -> 1366 bytes .../textures/gui/super_cooler_background.png | Bin 1537 -> 1553 bytes 13 files changed, 603 insertions(+), 50 deletions(-) create mode 100644 src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/EnergyRecipeComponent.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipe.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java index f9fdc6b..fc2fbec 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java @@ -1,6 +1,7 @@ package dev.ftb.ftbsba.tools; import com.mojang.serialization.Codec; +import dev.architectury.registry.registries.RegistrySupplier; import dev.ftb.ftbsba.FTBSBA; import dev.ftb.ftbsba.tools.content.CrookItem; import dev.ftb.ftbsba.tools.content.HammerItem; @@ -15,10 +16,7 @@ import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerContainer; import dev.ftb.ftbsba.tools.loot.CrookModifier; import dev.ftb.ftbsba.tools.loot.HammerModifier; -import dev.ftb.ftbsba.tools.recipies.CrookRecipe; -import dev.ftb.ftbsba.tools.recipies.CrookRecipeSerializer; -import dev.ftb.ftbsba.tools.recipies.HammerRecipe; -import dev.ftb.ftbsba.tools.recipies.HammerRecipeSerializer; +import dev.ftb.ftbsba.tools.recipies.*; import net.minecraft.ChatFormatting; import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; @@ -111,10 +109,18 @@ public interface ToolsRegistry { RegistryObject> HAMMER_LOOT_MODIFIER = LOOT_MODIFIERS_REGISTRY.register("hammer_loot_modifier", () -> HammerModifier.CODEC); RegistryObject> CROOK_LOOT_MODIFIER = LOOT_MODIFIERS_REGISTRY.register("crook_loot_modifier", () -> CrookModifier.CODEC); - RegistryObject> CROOK_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("crook", CrookRecipeSerializer::new); RegistryObject> CROOK_RECIPE_TYPE = RECIPE_TYPE_REGISTRY.register("crook", () -> new RecipeType<>() {}); - RegistryObject> HAMMER_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("hammer", HammerRecipeSerializer::new); + RegistryObject> CROOK_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("crook", CrookRecipeSerializer::new); + RegistryObject> HAMMER_RECIPE_TYPE = RECIPE_TYPE_REGISTRY.register("hammer", () -> new RecipeType<>() {}); + RegistryObject> HAMMER_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("hammer", HammerRecipeSerializer::new); + + RegistryObject> SUPER_COOLER_RECIPE_TYPE = RECIPE_TYPE_REGISTRY.register("super_cooler", () -> new RecipeType<>() {}); + RegistryObject> SUPER_COOLER_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("super_cooler", SuperCoolerRecipeSerializer::new); + + RegistryObject> FUSING_MACHINE_RECIPE_TYPE = RECIPE_TYPE_REGISTRY.register("fusing_machine", () -> new RecipeType<>() {}); + RegistryObject> FUSING_MACHINE_RECIPE_SERIALIZER = RECIPE_SERIALIZER_REGISTRY.register("fusing_machine", FusingMachineRecipeSerializer::new); + class ToolTipBlockItem extends BlockItem { private final Component tooltip; diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index 0b38447..78cf61c 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -8,6 +8,7 @@ import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -20,7 +21,6 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.EnergyStorage; -import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -35,6 +35,11 @@ public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider protected void onContentsChanged(int slot) { setChanged(); } + + @Override + public int getSlotLimit(int slot) { + return 1; + } }; public ItemStackHandler output = new ItemStackHandler(1) { @@ -44,7 +49,8 @@ protected void onContentsChanged(int slot) { } }; - public LazyOptional energy = LazyOptional.of(() -> new CustomEnergy(this)); + public CustomEnergy energy = new CustomEnergy(this); + public LazyOptional energyLazy = LazyOptional.of(() -> energy); public LazyOptional tank = LazyOptional.of(() -> new FluidTank(10000) { @Override @@ -55,51 +61,69 @@ protected void onContentsChanged() { public LazyOptional ioWrapper = LazyOptional.of(() -> new IOStackWrapper(inventory, output)); + /** + * Mostly borrowed from https://github.com/desht/ModularRouters/blob/MC1.20.1-master/src/main/java/me/desht/modularrouters/block/tile/ModularRouterBlockEntity.java#L1103-L1129 with permission. + * Thanks Desht! + */ ContainerData containerData = new ContainerData() { @Override public int get(int index) { - // Send energy and fluid levels to client - int energyStored = energy.map(IEnergyStorage::getEnergyStored).orElse(0); - - // Compact energy into two shorts - var compactedEnergyPartOne = energyStored & 0xFFFF; - var compactedEnergyPartTwo = (energyStored >> 16) & 0xFFFF; - - System.out.println("compactedEnergyPartOne: " + compactedEnergyPartOne); - System.out.println("compactedEnergyPartTwo: " + compactedEnergyPartTwo); - System.out.println("Original energyStored: " + energyStored); - - + int result = 0; + if (index == 0) { + result = energy.getEnergyStored() & 0x0000FFFF; + } else if (index == 1) { + result = (energy.getEnergyStored() & 0xFFFF0000) >> 16; + } else if (index == 2) { + return tank.map(IFluidTank::getFluid).map(FluidStack::getAmount).orElse(0); + } else if (index == 3) { + return progress; + } - return switch (index) { - case 0 -> compactedEnergyPartOne; - case 1 -> compactedEnergyPartTwo; - case 2 -> tank.map(IFluidTank::getFluidAmount).orElse(0); - default -> 0; - }; + return result; } @Override public void set(int index, int value) { - // No-op + if (value < 0) value += 65536; + + if (index == 0) { + energy.setEnergy(energy.getEnergyStored() & 0xFFFF0000 | value, false); + } else if (index == 1) { + energy.setEnergy(energy.getEnergyStored() & 0x0000FFFF | (value << 16), false); + } else if (index == 2) { + final int finalValue = value; + tank.ifPresent(tank -> tank.fill(new FluidStack(tank.getFluid(), finalValue), IFluidHandler.FluidAction.EXECUTE)); + } else if (index == 3) { + progress = value; + } } @Override public int getCount() { - return 3; + return 4; } }; + int progress = 0; + public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); } + public static void ticker(Level level, BlockPos pos, BlockState state, T t) { + if (!(t instanceof SuperCoolerBlockEntity entity)) { + return; + } + + + } + @Override public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { if (cap == ForgeCapabilities.ITEM_HANDLER) { return ioWrapper.cast(); } else if (cap == ForgeCapabilities.ENERGY) { - return energy.cast(); + return energyLazy.cast(); } else if (cap == ForgeCapabilities.FLUID_HANDLER) { return tank.cast(); } @@ -107,12 +131,6 @@ public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { return super.getCapability(cap, side); } - public static void ticker(Level level, BlockPos pos, BlockState state, T t) { - if (t instanceof SuperCoolerBlockEntity entity) { -// System.out.println("SuperCoolerBlockEntity.ticker"); - } - } - @Override public Component getDisplayName() { return Component.translatable("container.ftbsba.super_cooler"); // TODO: Add translation @@ -128,7 +146,7 @@ public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { public void invalidateCaps() { super.invalidateCaps(); ioWrapper.invalidate(); - energy.invalidate(); + energyLazy.invalidate(); tank.invalidate(); } @@ -140,7 +158,7 @@ public void load(CompoundTag arg) { wrapper.getInput().deserializeNBT(arg.getCompound("input")); wrapper.getInput().deserializeNBT(arg.getCompound("output")); }); - energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); + energyLazy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); tank.ifPresent(tank -> { ((FluidTank) tank).readFromNBT(arg.getCompound("fluid")); }); @@ -154,7 +172,7 @@ protected void saveAdditional(CompoundTag arg) { arg.put("input", wrapper.getInput().serializeNBT()); arg.put("output", wrapper.getInput().serializeNBT()); }); - energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); + energyLazy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); tank.ifPresent(tank -> { arg.put("fluid", ((FluidTank) tank).writeToNBT(new CompoundTag())); }); @@ -208,5 +226,12 @@ public int extractEnergy(int maxExtract, boolean simulate) { } return result; } + + public void setEnergy(int energy, boolean update) { + this.energy = energy; + if (update) { + this.entity.setChanged(); + } + } } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java index d998fa7..bfbc823 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java @@ -1,18 +1,24 @@ package dev.ftb.ftbsba.tools.content.supercooler; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; import dev.ftb.ftbsba.FTBSBA; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.IFluidTank; +import org.lwjgl.opengl.GL11; public class SuperCoolerScreen extends AbstractContainerScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/super_cooler_background.png"); @@ -27,10 +33,10 @@ public SuperCoolerScreen(SuperCoolerContainer arg, Inventory arg2, Component arg public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { super.render(arg, mouseX, mouseY, partialTicks); - var data = this.menu.entity.containerData; + var data = this.menu.containerData; if (mouseX > this.leftPos + 3 && mouseX < this.leftPos + 21 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { arg.pushPose(); - arg.translate(mouseX - 5, mouseY, 0); + arg.translate(mouseX - 5, mouseY, 600); arg.scale(0.6F, 0.6F, 0F); this.renderTooltip(arg, Component.literal(data.get(2) + " / " + this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0) + " mB"), 0, 0); arg.popPose(); @@ -39,13 +45,11 @@ public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { if (mouseX > this.leftPos + 166 && mouseX < this.leftPos + 174 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { var uncompressedEnergy = (data.get(0) & 0xFFFF) | (data.get(1) << 16); -// System.out.println(data.get(0) + " " + data.get(1) + " " + uncompressedEnergy); - - MutableComponent energyText = Component.literal(uncompressedEnergy + " / " + this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0) + " FE"); + MutableComponent energyText = Component.literal(uncompressedEnergy + " / " + this.menu.entity.energyLazy.map(IEnergyStorage::getMaxEnergyStored).orElse(0) + " FE"); int width = this.font.width(energyText); int scaledWidth = (int) (width * 0.6F); arg.pushPose(); - arg.translate(mouseX - 10 - scaledWidth, mouseY, 0); + arg.translate(mouseX - 10 - scaledWidth, mouseY, 600); arg.scale(0.6F, 0.6F, 0F); this.renderTooltip(arg, energyText, 0, 0); arg.popPose(); @@ -56,22 +60,96 @@ public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { protected void renderBg(PoseStack arg, float f, int i, int j) { renderBackground(arg); + arg.pushPose(); RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderTexture(0, TEXTURE); this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); - this.blit(arg, this.leftPos + 4, this.topPos + 6, 178, 3, 18, 67); + arg.popPose(); var data = this.menu.entity.containerData; + int combinedInt = data.get(0) & 0xFFFF | (data.get(1) & 0xFFFF) << 16; + int energyMax = this.menu.entity.energyLazy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); + int fluidMax = this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); + + arg.pushPose(); // Energy - int energyHeight = (int) (data.get(0) / (float) data.get(1) * 65); - this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4, 197, 4, 5, energyHeight); + float x = (float) combinedInt / energyMax; + int energyHeight = (int) (x * 65); + this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4 + 65 - energyHeight, 197, 4 + 65 - energyHeight, 5, energyHeight); + arg.popPose(); + + var fluid = this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); + if (fluid == null) { + return; + } + + var fluidExtensions = IClientFluidTypeExtensions.of(fluid.getFluid()); + var texture = fluidExtensions.getStillTexture(fluid); + var atlasSprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); // Fluid amount - int fluidHeight = (int) (data.get(2) / (float) data.get(3) * 65); - this.blit(arg, this.leftPos + 4, this.topPos + 6 + 65, 178, 71, 18, -fluidHeight); + int fluidHeight = (data.get(2) / fluidMax) * 65; + int textureHeight = 16; + + int tilesRequired = (int) Math.ceil((float) fluidHeight / textureHeight); + + arg.pushPose(); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + int[] cols = decomposeColor(fluidExtensions.getTintColor(fluid)); + + for (int k = 0; k < tilesRequired; k++) { + int height = Math.min(textureHeight, fluidHeight - k * textureHeight); + drawFluidTexture(arg, this.leftPos + 4, this.topPos + 6 + 48 - fluidHeight + k * textureHeight, atlasSprite, height, cols); + } + + RenderSystem.disableBlend(); + arg.popPose(); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + + // Fluid gauge + arg.pushPose(); + arg.translate(0, 0, 101); + this.blit(arg, this.leftPos + 4, this.topPos + 6, 178, 3, 18, 67); + arg.popPose(); + } + + private static void drawFluidTexture(PoseStack stack, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int[] cols) { + float uMin = textureSprite.getU0(); + float uMax = textureSprite.getU1(); + float vMin = textureSprite.getV0(); + float vMax = textureSprite.getV1(); + uMax = uMax - 0 / 16.0f * (uMax - uMin); + vMax = vMax - maskTop / 16.0f * (vMax - vMin); + + Matrix4f posMat = stack.last().pose(); + + Tesselator tessellator = Tesselator.getInstance(); + BufferBuilder worldrenderer = tessellator.getBuilder(); + worldrenderer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + worldrenderer.vertex(posMat, xCoord, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMax).endVertex(); + worldrenderer.vertex(posMat,xCoord + 16 - 0, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMax).endVertex(); + worldrenderer.vertex(posMat, xCoord + 16 - 0, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMin).endVertex(); + worldrenderer.vertex(posMat, xCoord, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMin).endVertex(); + tessellator.end(); + } + + public static int[] decomposeColor(int color) { + int[] res = new int[4]; + res[0] = color >> 24 & 0xff; + res[1] = color >> 16 & 0xff; + res[2] = color >> 8 & 0xff; + res[3] = color & 0xff; + return res; } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/EnergyRecipeComponent.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/EnergyRecipeComponent.java new file mode 100644 index 0000000..4737166 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/EnergyRecipeComponent.java @@ -0,0 +1,30 @@ +package dev.ftb.ftbsba.tools.integration.kubejs; + +import com.google.gson.JsonElement; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import dev.latvian.mods.kubejs.recipe.RecipeJS; +import dev.latvian.mods.kubejs.recipe.component.RecipeComponent; + +public class EnergyRecipeComponent implements RecipeComponent { + @Override + public Class componentClass() { + return SuperCoolerRecipe.EnergyComponent.class; + } + + @Override + public JsonElement write(RecipeJS recipe, SuperCoolerRecipe.EnergyComponent value) { + var obj = recipe.json; + obj.addProperty("fePerTick", value.fePerTick()); + obj.addProperty("ticksToProcess", value.ticksToProcess()); + return obj; + } + + @Override + public SuperCoolerRecipe.EnergyComponent read(RecipeJS recipe, Object from) { + var obj = recipe.json; + return new SuperCoolerRecipe.EnergyComponent( + obj.get("fePerTick").getAsInt(), + obj.get("ticksToProcess").getAsInt() + ); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java new file mode 100644 index 0000000..70e85d2 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java @@ -0,0 +1,17 @@ +package dev.ftb.ftbsba.tools.integration.kubejs; + +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import dev.latvian.mods.kubejs.fluid.OutputFluid; +import dev.latvian.mods.kubejs.item.InputItem; +import dev.latvian.mods.kubejs.recipe.RecipeKey; +import dev.latvian.mods.kubejs.recipe.component.FluidComponents; +import dev.latvian.mods.kubejs.recipe.component.ItemComponents; +import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; + +public interface FusingMachineRecipeSchema { + RecipeKey INGREDIENTS = ItemComponents.INPUT_ARRAY.key("ingredients"); + RecipeKey ENERGY = new EnergyRecipeComponent().key("energy"); + RecipeKey RESULT = FluidComponents.OUTPUT.key("result"); + + RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENTS, ENERGY); +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java index 84991de..bf5d937 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java @@ -10,5 +10,7 @@ public class KubeJSIntegration extends KubeJSPlugin { public void registerRecipeSchemas(RegisterRecipeSchemasEvent event) { event.register(new ResourceLocation(FTBSBA.MOD_ID, "hammer"), HammerRecipeSchema.SCHEMA); event.register(new ResourceLocation(FTBSBA.MOD_ID, "crook"), CrookRecipeSchema.SCHEMA); + event.register(new ResourceLocation(FTBSBA.MOD_ID, "fusing_machine"), FusingMachineRecipeSchema.SCHEMA); + event.register(new ResourceLocation(FTBSBA.MOD_ID, "super_cooler"), SuperCoolerRecipeSchema.SCHEMA); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java new file mode 100644 index 0000000..3d7a0c5 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java @@ -0,0 +1,20 @@ +package dev.ftb.ftbsba.tools.integration.kubejs; + +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import dev.latvian.mods.kubejs.fluid.InputFluid; +import dev.latvian.mods.kubejs.fluid.OutputFluid; +import dev.latvian.mods.kubejs.item.InputItem; +import dev.latvian.mods.kubejs.item.OutputItem; +import dev.latvian.mods.kubejs.recipe.RecipeKey; +import dev.latvian.mods.kubejs.recipe.component.FluidComponents; +import dev.latvian.mods.kubejs.recipe.component.ItemComponents; +import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; + +public interface SuperCoolerRecipeSchema { + RecipeKey INGREDIENTS = ItemComponents.INPUT_ARRAY.key("ingredients"); + RecipeKey FLUID = FluidComponents.INPUT.key("fluid"); + RecipeKey ENERGY = new EnergyRecipeComponent().key("energy"); + RecipeKey RESULT = ItemComponents.OUTPUT.key("result"); + + RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENTS, FLUID, ENERGY); +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipe.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipe.java new file mode 100644 index 0000000..c40aea6 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipe.java @@ -0,0 +1,85 @@ +package dev.ftb.ftbsba.tools.recipies; + +import com.google.common.base.MoreObjects; +import dev.ftb.ftbsba.tools.ToolsRegistry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; +import net.minecraftforge.fluids.FluidStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; + +public class FusingMachineRecipe implements Recipe { + private final ResourceLocation id; + public String group; + + public List ingredients; + public FluidStack fluidResult; + public SuperCoolerRecipe.EnergyComponent energyComponent; + + public FusingMachineRecipe(ResourceLocation i, String g) { + this.id = i; + this.group = g; + + this.ingredients = new ArrayList<>(); + this.fluidResult = FluidStack.EMPTY; + this.energyComponent = new SuperCoolerRecipe.EnergyComponent(0, 0); + } + + @Override + public boolean matches(NoInventory inv, Level world) { + return true; + } + + @Override + public ItemStack assemble(NoInventory inv) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public ItemStack getResultItem() { + return ItemStack.EMPTY; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + + @Override + public String getGroup() { + return this.group; + } + + @Override + public RecipeSerializer getSerializer() { + return ToolsRegistry.FUSING_MACHINE_RECIPE_SERIALIZER.get(); + } + + @Override + public RecipeType getType() { + return ToolsRegistry.FUSING_MACHINE_RECIPE_TYPE.get(); + } + + @Override + public String toString() { + return new StringJoiner(", ", FusingMachineRecipe.class.getSimpleName() + "[", "]") + .add("id=" + id) + .add("group='" + group + "'") + .add("ingredients=" + ingredients) + .add("fluidResult=" + fluidResult) + .add("energyComponent=" + energyComponent) + .toString(); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java new file mode 100644 index 0000000..45101a7 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java @@ -0,0 +1,90 @@ +package dev.ftb.ftbsba.tools.recipies; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.ShapedRecipe; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; + +public class FusingMachineRecipeSerializer implements RecipeSerializer { + @Override + public FusingMachineRecipe fromJson(ResourceLocation id, JsonObject json) { + var recipe = new FusingMachineRecipe(id, json.has("group") ? json.get("group").getAsString() : ""); + + var ingredients = json.get("ingredients").getAsJsonArray(); + for (JsonElement e : ingredients) { + recipe.ingredients.add(Ingredient.fromJson(e)); + } + + var fluidResult = json.get("result").getAsJsonObject(); + recipe.fluidResult = FluidStackSerializer.deserialize(fluidResult); + recipe.energyComponent = SuperCoolerRecipe.EnergyComponent.fromJson(json.get("energy")); + + return null; + } + + @Override + public @Nullable FusingMachineRecipe fromNetwork(ResourceLocation arg, FriendlyByteBuf arg2) { + var groups = arg2.readUtf(); + + Ingredient[] ingredients = new Ingredient[3]; + for (int i = 0; i < 3; i++) { + ingredients[i] = Ingredient.fromNetwork(arg2); + } + + FluidStack fluidResult = FluidStack.readFromPacket(arg2); + SuperCoolerRecipe.EnergyComponent energyComponent = SuperCoolerRecipe.EnergyComponent.fromNetwork(arg2); + + var recipe = new FusingMachineRecipe(arg, groups); + Collections.addAll(recipe.ingredients, ingredients); + recipe.fluidResult = fluidResult; + recipe.energyComponent = energyComponent; + + return recipe; + } + + @Override + public void toNetwork(FriendlyByteBuf buffer, FusingMachineRecipe recipe) { + buffer.writeUtf(recipe.group); + + for (Ingredient i : recipe.ingredients) { + i.toNetwork(buffer); + } + + recipe.fluidResult.writeToPacket(buffer); + recipe.energyComponent.toNetwork(buffer); + } + + public static class FluidStackSerializer { + public static JsonElement serialize(FluidStack stack) { + JsonObject o = new JsonObject(); + var fluidLookup = ForgeRegistries.FLUIDS.getKey(stack.getFluid()); + if (fluidLookup == null) { + throw new RuntimeException("Fluid " + stack.getFluid() + " is not registered"); + } + + o.addProperty("fluid", fluidLookup.toString()); + o.addProperty("amount", stack.getAmount()); + return o; + } + + public static FluidStack deserialize(JsonElement element) { + JsonObject o = element.getAsJsonObject(); + var fluid = ForgeRegistries.FLUIDS.getValue(new ResourceLocation(o.get("fluid").getAsString())); + if (fluid == null) { + throw new RuntimeException("Fluid " + o.get("fluid").getAsString() + " is not registered"); + } + + return new FluidStack(fluid, o.get("amount").getAsInt()); + } + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java new file mode 100644 index 0000000..2b18662 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java @@ -0,0 +1,130 @@ +package dev.ftb.ftbsba.tools.recipies; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import dev.ftb.ftbsba.tools.ToolsRegistry; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; +import net.minecraftforge.fluids.FluidStack; + +import java.util.ArrayList; +import java.util.List; + +public class SuperCoolerRecipe implements Recipe { + private final ResourceLocation id; + public String group; + public List ingredients; + public EnergyComponent energyComponent; + public FluidStack fluidIngredient; + + public ItemStack result; + + public SuperCoolerRecipe(ResourceLocation i, String g) { + this.id = i; + this.group = g; + + this.ingredients = new ArrayList<>(); + this.energyComponent = new EnergyComponent(0, 0); + this.fluidIngredient = FluidStack.EMPTY; + + this.result = ItemStack.EMPTY; + } + + @Override + public boolean matches(NoInventory inv, Level world) { +// LazyOptional ioWrapper = inv.ioWrapper; +// if (!ioWrapper.isPresent()) { +// return false; +// } +// +// IOStackWrapper io = ioWrapper.orElseThrow(RuntimeException::new); +// ItemStackHandler input = io.getInput(); +// +// var filledIngredients = ingredients.stream().filter(e -> !e.isEmpty()).toList(); +// for (var ingredient : filledIngredients) { +// for (int i = 0; i < input.getSlots(); i++) { +// if (!ingredient.test(input.getStackInSlot(i))) { +// // If any of the ingredients don't match, return false +// return false; +// } +// } +// } +// +// // Now test the fluid +// if (!fluidIngredient.isEmpty()) { +// if (!inv.tank.isPresent()) { +// return false; +// } +// +// var entityFluid = inv.tank.orElseThrow(RuntimeException::new).getFluid(); +// return fluidIngredient.isFluidEqual(entityFluid) && fluidIngredient.getAmount() <= entityFluid.getAmount(); +// } +// +// return true; + + return true; + } + + @Override + public ItemStack assemble(NoInventory inv) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public ItemStack getResultItem() { + return ItemStack.EMPTY; + } + + @Override + public ResourceLocation getId() { + return this.id; + } + + @Override + public String getGroup() { + return this.group; + } + + @Override + public RecipeSerializer getSerializer() { + return ToolsRegistry.SUPER_COOLER_RECIPE_SERIALIZER.get(); + } + + @Override + public RecipeType getType() { + return ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get(); + } + + public record EnergyComponent(int fePerTick, int ticksToProcess) { + public static EnergyComponent fromJson(JsonElement element) { + return new EnergyComponent(element.getAsJsonObject().get("fePerTick").getAsInt(), element.getAsJsonObject().get("ticksToProcess").getAsInt()); + } + + public JsonElement toJson() { + var element = new JsonObject(); + element.addProperty("fePerTick", fePerTick); + element.addProperty("ticksToProcess", ticksToProcess); + return element; + } + + public static EnergyComponent fromNetwork(FriendlyByteBuf buffer) { + return new EnergyComponent(buffer.readInt(), buffer.readInt()); + } + + public void toNetwork(FriendlyByteBuf buffer) { + buffer.writeInt(fePerTick); + buffer.writeInt(ticksToProcess); + } + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java new file mode 100644 index 0000000..fafa148 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java @@ -0,0 +1,70 @@ +package dev.ftb.ftbsba.tools.recipies; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.ShapedRecipe; +import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +public class SuperCoolerRecipeSerializer implements RecipeSerializer { + + @Override + public SuperCoolerRecipe fromJson(ResourceLocation arg, JsonObject jsonObject) { + var recipe = new SuperCoolerRecipe(arg, jsonObject.has("group") ? jsonObject.get("group").getAsString() : ""); + + var ingredients = jsonObject.get("ingredients").getAsJsonArray(); + for (JsonElement e : ingredients) { + recipe.ingredients.add(Ingredient.fromJson(e)); + } + + var fluidIngredient = jsonObject.get("fluid").getAsJsonObject(); + recipe.fluidIngredient = FusingMachineRecipeSerializer.FluidStackSerializer.deserialize(fluidIngredient); + recipe.energyComponent = SuperCoolerRecipe.EnergyComponent.fromJson(jsonObject.get("energy")); + + recipe.result = ShapedRecipe.itemStackFromJson(jsonObject.get("result").getAsJsonObject()); + + return recipe; + } + + @Override + public @Nullable SuperCoolerRecipe fromNetwork(ResourceLocation arg, FriendlyByteBuf arg2) { + var groups = arg2.readUtf(); + + Ingredient[] ingredients = new Ingredient[3]; + for (int i = 0; i < 3; i++) { + ingredients[i] = Ingredient.fromNetwork(arg2); + } + + FluidStack fluidIngredient = FluidStack.readFromPacket(arg2); + SuperCoolerRecipe.EnergyComponent energyComponent = SuperCoolerRecipe.EnergyComponent.fromNetwork(arg2); + + var recipe = new SuperCoolerRecipe(arg, groups); + recipe.ingredients.addAll(Arrays.asList(ingredients)); + recipe.fluidIngredient = fluidIngredient; + recipe.energyComponent = energyComponent; + recipe.result = arg2.readItem(); + + return recipe; + } + + @Override + public void toNetwork(FriendlyByteBuf arg, SuperCoolerRecipe arg2) { + arg.writeUtf(arg2.group); + + for (Ingredient i : arg2.ingredients) { + i.toNetwork(arg); + } + + arg2.fluidIngredient.writeToPacket(arg); + arg2.energyComponent.toNetwork(arg); + arg.writeItem(arg2.result); + } +} diff --git a/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.png b/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.png index 199ad6acef439e5df0fdee7c12e463cd548e61a7..55e8e33e5b185e0d4aec259cee1cbb3eba2edbc0 100644 GIT binary patch literal 1366 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K+cB%pAc6d z{r~^}W5%; zyu;JQF{EP7+dH{MvkgRA6D^mu$d=r3z4-V2GKW74i)w|W4zrj#s$6c zJGc+DTlik~WB4YLF{_U0$M2~RTVualF41YI`lH|QT4%fZf%k^nITa?_Co?b{;B-jh z`@lMZgMp!fDS>YTFje?7oMAL$V0gg!;IrIzhE4{C26cva%sC7eEDx^RgztX3m+{$G zy|UAS44W(yln3A>+@CF4aa~z~ zbAnLCb;|>P1wYh(diL3Y%ZYK4)N_aQmxrL&3b$4`dW}pFXKM;eM%5!|IkQWaLM1|VmTtAU7!)OzaQ9%q(V(dA&%5|;87DkF8E|;+gHJBz zOb_csZ&>^bW_Dpe@ayDy2JcIW?t)ShhY!`gZ9dEy9oyYJw z{;04#^VPhW%p#!N3jq$fhgl)424==-e?pg(oxbPpkb1uUjhG)OW21ou1`fIB>noH} zwiO`EK&WYD%&PuZ{6lzQF$+-e2KRz(=?8!YGE9yAvV$L?49aTw3slZ_Cir0rF!`7} zY-V?m?Ov^aj*r1qXWc%FqsQY5yjJVgAGH^~k+b T>=DmqP$+o1`njxgN@xNAR1(zO literal 1371 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K+f9$pAc6d z{r~^}W5olJnz*mk8vo_6n7KSyfW?~2cg0H+ zU*TO_I`5R1{%2c%X0E_1?zy|zGlF;Dl3O6R$H~7yFNYtKV2(h`1)b$Y=%7> zSFZZStYF8wYSmlDy01G+*XPXou2;$U;G;dmt#4MR-ZFmpJdeM@rSAS`CWgl!xfL9^ z6b#v?uukY;V4A}6Kt{lwfzgYpfUiTjfkBmVPyMop1{W5A1u6{hnICa%;6Bh_xbEY$ z>ueI&cOQxV#&FszXA2)m3^*{UKmS@i^WqZyyw5lIwe8;kX;=x{rAA7jg$oyZ)$i{x))5#Ba82a_6@%=x;(A?j% zZl_osrocI4ov<)kZfCB>~3ej+e!M*z5W8sAv-OHicU?zdM6C@vGoUbpdS1RcPnIFw4 z^H#E8Pil5UbL^Kr{FtV_W$gRLb7T3TlN<^THyN&qF|ht8N0t_~6@vd$@? F2>|*L_A>wg diff --git a/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png b/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png index ed21bff3dedbb478159739955e8fb7862c930a38..0d67dc66f99de93d718bd630d7c82e321eaa20af 100644 GIT binary patch delta 830 zcmZqVnaHz&m8t%_r;B4q#hkZyZs#pF5NS=E6mUv9WM=!5zxwPa7-#LBs3CEU?Z5Y| z?n^UEeoii2p+pNH5U*!_r&>D>?g z>&sX<4E~+on#I`Gb^QyIY{OpGQ=2LoVvcH_Ud8^SYRTKs>-TeonCtJ@71cAYIBw7I zr)1}M2ETu$j0_Dv40B8s^cmE5Gt|^Rnt$V!=VjSN zkLrLyepgY;d16}3-nTn$EvT-1e%!1-x#XMl^N>}?4XxJe*ZVX4j-2Vru+`ROY2`Wn zuZB*cU-w*`+uYJs$F^o3Q~l)sb|-nK8O^WV#>O#!(f<=EUC|Db@Klg zGP(&T{7kCIY4|Sg-Cm#4P$dxYIqnD3hWU)$WlxzGypwObX3xEc@yxRFE!y+d89JGO z9)$pb+#OKX2IYpoJP}*8qt7=a{I>tbwSD45VeSbM3b+38TRS}ibECoB^Y5&kj&lHY zZ4hgTe~DWM4fU^-n1 delta 815 zcmbQp)5x=dm8t%@r;B4q#hkZyE>2oxAky-1ja5(n2CMh~7ice-q}Z-Co#j`{pIY_2 z%;(xdGj&`!78)1HChy&vEhp=A<#Ci<|HuD^Ms-tvUR(E)twFCUQs#i%laC)foM|qdDOWlRtx) zd(n>*!3P*T__wnr$k=_7n!pgz{`q>t{nZWW44(^}gAdr<;XB~8Du%glgYp#C2Wjpe zY!6boO!y00{!8clrbT*l8pf|GdUVzB@l{F27H(Vh;0bTd@Dm?|v6?riVYZCs_Vl#kfc~;crre z`GMa@Z#}%uQ!tmMsE#|H;iYZDy}mOH>khjH{M&j!TH)rGZ)GWb0UAK>LBYK?ZV4#U znrX@RhDz&AUnL*p{8zUwqdc6L} p%}1?FlO0)iOip0smAGtkz<%ng-ydWY)p$XMdAj Date: Fri, 9 Feb 2024 20:34:42 +0000 Subject: [PATCH 4/9] feat: kinda functionality? --- .../supercooler/SuperCoolerBlockEntity.java | 101 ++++++++++++++++++ .../tools/recipies/SuperCoolerRecipe.java | 30 ------ 2 files changed, 101 insertions(+), 30 deletions(-) diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index 78cf61c..d4b8361 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -1,6 +1,8 @@ package dev.ftb.ftbsba.tools.content.supercooler; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.recipies.NoInventory; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import dev.ftb.ftbsba.tools.utils.IOStackWrapper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -105,6 +107,8 @@ public int getCount() { }; int progress = 0; + SuperCoolerRecipe processingRecipe = null; + SuperCoolerRecipe lastProcessedRecipe = null; public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); @@ -115,7 +119,104 @@ public static void ticker(Level level, BlockPos pos, Blo return; } + if (level.isClientSide) { + return; + } + + if (!entity.hasEnergy() || !entity.hasFluid() || !entity.hasItemInAnySlot()) { + entity.progress = 0; + return; + } + + // We should test for the recipe here + if (entity.progress == 0) { + SuperCoolerRecipe recipe = entity.testForRecipe(); + if (recipe == null) { + return; + } + + entity.progress = 1; + entity.processingRecipe = recipe; + } else if (entity.progress >= 100) { + entity.progress = 0; + entity.executeRecipe(); + entity.processingRecipe = null; + } else { + // Use energy + entity.progress++; + } + } + + public void executeRecipe() { + // Extract the fluid + // Extract the items + // Produce the result + } + + private boolean hasFluid() { + return tank.map(IFluidTank::getFluid).map(FluidStack::isEmpty).orElse(true); + } + + private boolean hasEnergy() { + return energy.getEnergyStored() > 0; + } + + private boolean hasItemInAnySlot() { + if (!ioWrapper.isPresent()) { + return true; + } + + var input = ioWrapper.orElseThrow(RuntimeException::new).getInput(); + for (int i = 0; i < input.getSlots(); i++) { + if (!input.getStackInSlot(i).isEmpty()) { + return true; + } + } + + return false; + } + + @Nullable + private SuperCoolerRecipe testForRecipe() { + LazyOptional ioWrapper = this.ioWrapper; + if (!ioWrapper.isPresent()) { + return null; + } + + var recipes = this.level.getServer().getRecipeManager().getAllRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get(), NoInventory.INSTANCE, this.level); + if (recipes.isEmpty()) { + return null; + } + + if (!this.tank.isPresent()) { + return null; + } + + var recipesForFluid = recipes.stream() + .filter(e -> !e.fluidIngredient.isEmpty()) + .filter(e -> e.fluidIngredient.isFluidEqual(this.tank.orElseThrow(RuntimeException::new).getFluid())) + .filter(e -> e.fluidIngredient.getAmount() <= this.tank.orElseThrow(RuntimeException::new).getFluidAmount()) + .toList(); + + for (var recipe : recipesForFluid) { + IOStackWrapper io = ioWrapper.orElseThrow(RuntimeException::new); + ItemStackHandler input = io.getInput(); + + var filledIngredients = recipe.ingredients.stream().filter(e -> !e.isEmpty()).toList(); + for (var ingredient : filledIngredients) { + for (int i = 0; i < input.getSlots(); i++) { + if (!ingredient.test(input.getStackInSlot(i))) { + // If any of the ingredients don't match, return false + return null; + } + } + } + + // The fluid and fluid amount has to already match thus we don't need to check it again + return recipe; + } + return null; } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java index 2b18662..0cf922c 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java @@ -38,36 +38,6 @@ public SuperCoolerRecipe(ResourceLocation i, String g) { @Override public boolean matches(NoInventory inv, Level world) { -// LazyOptional ioWrapper = inv.ioWrapper; -// if (!ioWrapper.isPresent()) { -// return false; -// } -// -// IOStackWrapper io = ioWrapper.orElseThrow(RuntimeException::new); -// ItemStackHandler input = io.getInput(); -// -// var filledIngredients = ingredients.stream().filter(e -> !e.isEmpty()).toList(); -// for (var ingredient : filledIngredients) { -// for (int i = 0; i < input.getSlots(); i++) { -// if (!ingredient.test(input.getStackInSlot(i))) { -// // If any of the ingredients don't match, return false -// return false; -// } -// } -// } -// -// // Now test the fluid -// if (!fluidIngredient.isEmpty()) { -// if (!inv.tank.isPresent()) { -// return false; -// } -// -// var entityFluid = inv.tank.orElseThrow(RuntimeException::new).getFluid(); -// return fluidIngredient.isFluidEqual(entityFluid) && fluidIngredient.getAmount() <= entityFluid.getAmount(); -// } -// -// return true; - return true; } From 5dc67fca7ad40e20c0e4096f1efcfc63133f4099 Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Sat, 10 Feb 2024 14:46:15 +0000 Subject: [PATCH 5/9] feat: super cooler is working as expected chore: a lot of bug fixing --- .../java/dev/ftb/ftbsba/tools/ToolsData.java | 2 + .../supercooler/SuperCoolerBlockEntity.java | 166 +++++++++++++++--- .../supercooler/SuperCoolerContainer.java | 21 ++- .../supercooler/SuperCoolerScreen.java | 21 ++- .../kubejs/FusingMachineRecipeSchema.java | 13 +- .../integration/kubejs/KubeJSIntegration.java | 1 + .../kubejs/SuperCoolerRecipeSchema.java | 13 +- .../gui/fusing_machine_background.png | Bin 1366 -> 1757 bytes .../textures/gui/super_cooler_background.png | Bin 1553 -> 1811 bytes 9 files changed, 201 insertions(+), 36 deletions(-) diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java index ab0e26a..dca1361 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java @@ -12,6 +12,7 @@ import net.minecraft.data.loot.BlockLoot; import net.minecraft.data.loot.LootTableProvider; import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeBuilder; import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.tags.BlockTagsProvider; @@ -316,6 +317,7 @@ private void autoHammer(ItemLike output, Item center, Item top, Consumer head, Consumer consumer) { diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index d4b8361..8e5f871 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -1,21 +1,21 @@ package dev.ftb.ftbsba.tools.content.supercooler; import dev.ftb.ftbsba.tools.ToolsRegistry; -import dev.ftb.ftbsba.tools.recipies.NoInventory; import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import dev.ftb.ftbsba.tools.utils.IOStackWrapper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -36,11 +36,9 @@ public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider @Override protected void onContentsChanged(int slot) { setChanged(); - } - - @Override - public int getSlotLimit(int slot) { - return 1; + if (progress > 0) { + progress = 0; + } } }; @@ -79,6 +77,8 @@ public int get(int index) { return tank.map(IFluidTank::getFluid).map(FluidStack::getAmount).orElse(0); } else if (index == 3) { return progress; + } else if (index == 4) { + return progressRequired; } return result; @@ -94,21 +94,30 @@ public void set(int index, int value) { energy.setEnergy(energy.getEnergyStored() & 0x0000FFFF | (value << 16), false); } else if (index == 2) { final int finalValue = value; - tank.ifPresent(tank -> tank.fill(new FluidStack(tank.getFluid(), finalValue), IFluidHandler.FluidAction.EXECUTE)); + tank.ifPresent(tank -> { + // If the value is greater than the previous value, we're filling the tank + if (finalValue > tank.getFluidAmount()) { + tank.fill(new FluidStack(tank.getFluid(), finalValue - tank.getFluidAmount()), IFluidHandler.FluidAction.EXECUTE); + } else { + tank.drain(tank.getFluidAmount() - finalValue, IFluidHandler.FluidAction.EXECUTE); + } + }); } else if (index == 3) { progress = value; + } else if (index == 4) { + progressRequired = value; } } @Override public int getCount() { - return 4; + return 5; } }; int progress = 0; + int progressRequired = 0; SuperCoolerRecipe processingRecipe = null; - SuperCoolerRecipe lastProcessedRecipe = null; public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); @@ -135,26 +144,110 @@ public static void ticker(Level level, BlockPos pos, Blo return; } + if (!entity.canAcceptOutput(recipe)) { + return; + } + entity.progress = 1; entity.processingRecipe = recipe; - } else if (entity.progress >= 100) { - entity.progress = 0; + entity.progressRequired = recipe.energyComponent.ticksToProcess(); + } else if (entity.progress >= entity.progressRequired) { entity.executeRecipe(); - entity.processingRecipe = null; + entity.breakProgress(); } else { // Use energy + entity.useEnergy(); entity.progress++; } } public void executeRecipe() { + // This shouldn't be possible, but we'll check because we have to + var tank = this.tank.orElseThrow(RuntimeException::new); + var ioWrapper = this.ioWrapper.orElseThrow(RuntimeException::new); + // Extract the fluid + int requiredFluid = this.processingRecipe.fluidIngredient.getAmount(); + var fluidResult = tank.drain(requiredFluid, IFluidHandler.FluidAction.SIMULATE); + if (fluidResult.isEmpty() || fluidResult.getAmount() < requiredFluid) { + breakProgress(); + return; + } + // Extract the items + // First test if we can extract the items by simulating and validating the result + var requiredItems = this.processingRecipe.ingredients; + for (var ingredient : requiredItems) { + for (int i = 0; i < ioWrapper.getInput().getSlots(); i++) { + var stack = ioWrapper.getInput().getStackInSlot(i); + if (ingredient.test(stack)) { + var result = ioWrapper.getInput().extractItem(i, 1, true); + if (result.isEmpty()) { + breakProgress(); + return; + } + } + } + } + + // Do everything + tank.drain(requiredFluid, IFluidHandler.FluidAction.EXECUTE); + for (var ingredient : requiredItems) { + for (int i = 0; i < ioWrapper.getInput().getSlots(); i++) { + var stack = ioWrapper.getInput().getStackInSlot(i); + if (ingredient.test(stack)) { + // This logically can't be false due to the simulation above + ioWrapper.getInput().extractItem(i, 1, false); + } + } + } + // Produce the result + ioWrapper.getOutput().insertItem(0, this.processingRecipe.result.copy(), false); + } + + private void useEnergy() { + if (this.processingRecipe == null) { + return; + } + + var result = this.energy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), true); + if (result < this.processingRecipe.energyComponent.fePerTick()) { + breakProgress(); + return; + } + + this.energy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), false); + } + + /** + * This will always force us back to the start of the recipe + */ + private void breakProgress() { + this.progress = 0; + this.progressRequired = 0; + this.processingRecipe = null; + } + + public boolean canAcceptOutput(SuperCoolerRecipe recipe) { + var output = this.ioWrapper.orElseThrow(RuntimeException::new).getOutput(); + var outputSlot = output.getStackInSlot(0); + + if (outputSlot.isEmpty()) { + return true; + } + + // Do we have room for the result? + if (outputSlot.getCount() >= outputSlot.getMaxStackSize()) { + return false; + } + + // Are the items the same? + return outputSlot.sameItem(recipe.result); } private boolean hasFluid() { - return tank.map(IFluidTank::getFluid).map(FluidStack::isEmpty).orElse(true); + return tank.map(IFluidTank::getFluid).map(e -> !e.isEmpty()).orElse(false); } private boolean hasEnergy() { @@ -176,6 +269,10 @@ private boolean hasItemInAnySlot() { return false; } + /** + * Concerned this is too complex for a per tick operation. + * @return The recipe to process, or null if no recipe can be processed + */ @Nullable private SuperCoolerRecipe testForRecipe() { LazyOptional ioWrapper = this.ioWrapper; @@ -183,7 +280,8 @@ private SuperCoolerRecipe testForRecipe() { return null; } - var recipes = this.level.getServer().getRecipeManager().getAllRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get(), NoInventory.INSTANCE, this.level); + // Does this cache? I haven't looked yet + var recipes = this.level.getServer().getRecipeManager().getAllRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get()); if (recipes.isEmpty()) { return null; } @@ -192,6 +290,19 @@ private SuperCoolerRecipe testForRecipe() { return null; } + boolean hasOccupiedSlot = false; + for (int i = 0; i < this.inventory.getSlots(); i++) { + if (!this.inventory.getStackInSlot(i).isEmpty()) { + hasOccupiedSlot = true; + break; + } + } + + // No items in the input slots = no recipe + if (!hasOccupiedSlot) { + return null; + } + var recipesForFluid = recipes.stream() .filter(e -> !e.fluidIngredient.isEmpty()) .filter(e -> e.fluidIngredient.isFluidEqual(this.tank.orElseThrow(RuntimeException::new).getFluid())) @@ -203,16 +314,29 @@ private SuperCoolerRecipe testForRecipe() { ItemStackHandler input = io.getInput(); var filledIngredients = recipe.ingredients.stream().filter(e -> !e.isEmpty()).toList(); - for (var ingredient : filledIngredients) { - for (int i = 0; i < input.getSlots(); i++) { - if (!ingredient.test(input.getStackInSlot(i))) { - // If any of the ingredients don't match, return false - return null; + System.out.println(filledIngredients.size()); + NonNullList foundIngredients = NonNullList.create(); + + for (int i = 0; i < input.getSlots(); i++) { + var stack = input.getStackInSlot(i); + if (stack.isEmpty()) { + continue; + } + + for (var ingredient : filledIngredients) { + if (ingredient.test(stack)) { + foundIngredients.add(ingredient); } } } - // The fluid and fluid amount has to already match thus we don't need to check it again + // Compare the found ingredients to the recipe ingredients + for (var ingredient : recipe.ingredients) { + if (!foundIngredients.contains(ingredient)) { + return null; + } + } + return recipe; } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java index a87bc65..1b193ee 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java @@ -12,8 +12,10 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.SlotItemHandler; +import org.jetbrains.annotations.NotNull; public class SuperCoolerContainer extends AbstractContainerMenu { SuperCoolerBlockEntity entity; @@ -29,7 +31,7 @@ protected SuperCoolerContainer(int i, ContainerData containerData, Inventory arg addSlot(new SlotItemHandler(inventory.getInput(), 0, 42, startY)); addSlot(new SlotItemHandler(inventory.getInput(), 1, 42, startY + 18)); addSlot(new SlotItemHandler(inventory.getInput(), 2, 42, startY + (18 * 2))); - addSlot(new SlotItemHandler(inventory.getOutput(), 0, 122, startY + 19)); + addSlot(new ExtractOnlySlot(inventory.getOutput(), 0, 122, startY + 19)); }); this.containerData = containerData; @@ -53,11 +55,11 @@ public ItemStack quickMoveStack(Player arg, int index) { ItemStack currentStack = slot.getItem(); itemstack = currentStack.copy(); - if (index < 3) { - if (!this.moveItemStackTo(currentStack, 3, this.slots.size(), false)) { + if (index > 35) { + if (!this.moveItemStackTo(currentStack, 0, 36, false)) { return ItemStack.EMPTY; } - } else if (!this.moveItemStackTo(currentStack, 0, 3, false)) { + } else if (!this.moveItemStackTo(currentStack, 36, 39, false)) { return ItemStack.EMPTY; } @@ -82,4 +84,15 @@ public void slotsChanged(Container arg) { super.slotsChanged(arg); this.entity.setChanged(); } + + public static class ExtractOnlySlot extends SlotItemHandler { + public ExtractOnlySlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return false; + } + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java index bfbc823..3d57a9a 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java @@ -14,6 +14,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractFurnaceMenu; import net.minecraft.world.inventory.InventoryMenu; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.energy.IEnergyStorage; @@ -54,6 +55,8 @@ public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { this.renderTooltip(arg, energyText, 0, 0); arg.popPose(); } + + renderTooltip(arg, mouseX, mouseY); } @Override @@ -75,12 +78,18 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { int fluidMax = this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); arg.pushPose(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 0.8F); + // Energy float x = (float) combinedInt / energyMax; int energyHeight = (int) (x * 65); this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4 + 65 - energyHeight, 197, 4 + 65 - energyHeight, 5, energyHeight); arg.popPose(); + RenderSystem.disableBlend(); + var fluid = this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); if (fluid == null) { return; @@ -91,10 +100,10 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { var atlasSprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); // Fluid amount - int fluidHeight = (data.get(2) / fluidMax) * 65; + float fluidHeight = (float) data.get(2) / fluidMax * 65; int textureHeight = 16; - int tilesRequired = (int) Math.ceil((float) fluidHeight / textureHeight); + int tilesRequired = (int) Math.ceil(fluidHeight / textureHeight); arg.pushPose(); RenderSystem.setShader(GameRenderer::getPositionColorTexShader); @@ -106,8 +115,8 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { int[] cols = decomposeColor(fluidExtensions.getTintColor(fluid)); for (int k = 0; k < tilesRequired; k++) { - int height = Math.min(textureHeight, fluidHeight - k * textureHeight); - drawFluidTexture(arg, this.leftPos + 4, this.topPos + 6 + 48 - fluidHeight + k * textureHeight, atlasSprite, height, cols); + int height = 16 - (int) Math.min(textureHeight, fluidHeight - k * textureHeight); + drawFluidTexture(arg, this.leftPos + 4, this.topPos + 6 + 47 - (k * textureHeight), atlasSprite, height, cols); } RenderSystem.disableBlend(); @@ -121,6 +130,10 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { arg.translate(0, 0, 101); this.blit(arg, this.leftPos + 4, this.topPos + 6, 178, 3, 18, 67); arg.popPose(); + + // Finally, draw the progress bar + float computedPercentage = data.get(4) == 0 ? 0 : (float) data.get(3) / data.get(4) * 24; + this.blit(arg, this.leftPos + 80, this.topPos + 28, 203, 0, (int) computedPercentage + 1, 16); } private static void drawFluidTexture(PoseStack stack, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int[] cols) { diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java index 70e85d2..fd3c9cf 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/FusingMachineRecipeSchema.java @@ -1,17 +1,22 @@ package dev.ftb.ftbsba.tools.integration.kubejs; -import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import dev.latvian.mods.kubejs.fluid.OutputFluid; import dev.latvian.mods.kubejs.item.InputItem; import dev.latvian.mods.kubejs.recipe.RecipeKey; -import dev.latvian.mods.kubejs.recipe.component.FluidComponents; -import dev.latvian.mods.kubejs.recipe.component.ItemComponents; +import dev.latvian.mods.kubejs.recipe.component.*; import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; +import dev.latvian.mods.kubejs.util.TinyMap; public interface FusingMachineRecipeSchema { RecipeKey INGREDIENTS = ItemComponents.INPUT_ARRAY.key("ingredients"); - RecipeKey ENERGY = new EnergyRecipeComponent().key("energy"); RecipeKey RESULT = FluidComponents.OUTPUT.key("result"); + RecipeKey> ENERGY = new MapRecipeComponent<>( + StringComponent.ANY, + NumberComponent.INT, + false + ) + .key("energy"); + RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENTS, ENERGY); } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java index bf5d937..f729be9 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/KubeJSIntegration.java @@ -12,5 +12,6 @@ public void registerRecipeSchemas(RegisterRecipeSchemasEvent event) { event.register(new ResourceLocation(FTBSBA.MOD_ID, "crook"), CrookRecipeSchema.SCHEMA); event.register(new ResourceLocation(FTBSBA.MOD_ID, "fusing_machine"), FusingMachineRecipeSchema.SCHEMA); event.register(new ResourceLocation(FTBSBA.MOD_ID, "super_cooler"), SuperCoolerRecipeSchema.SCHEMA); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java index 3d7a0c5..b444cf6 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java @@ -6,14 +6,21 @@ import dev.latvian.mods.kubejs.item.InputItem; import dev.latvian.mods.kubejs.item.OutputItem; import dev.latvian.mods.kubejs.recipe.RecipeKey; -import dev.latvian.mods.kubejs.recipe.component.FluidComponents; -import dev.latvian.mods.kubejs.recipe.component.ItemComponents; +import dev.latvian.mods.kubejs.recipe.component.*; import dev.latvian.mods.kubejs.recipe.schema.RecipeSchema; +import dev.latvian.mods.kubejs.util.TinyMap; public interface SuperCoolerRecipeSchema { RecipeKey INGREDIENTS = ItemComponents.INPUT_ARRAY.key("ingredients"); RecipeKey FLUID = FluidComponents.INPUT.key("fluid"); - RecipeKey ENERGY = new EnergyRecipeComponent().key("energy"); + + RecipeKey> ENERGY = new MapRecipeComponent<>( + StringComponent.ANY, + NumberComponent.INT, + false + ) + .key("energy"); + RecipeKey RESULT = ItemComponents.OUTPUT.key("result"); RecipeSchema SCHEMA = new RecipeSchema(RESULT, INGREDIENTS, FLUID, ENERGY); diff --git a/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.png b/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.png index 55e8e33e5b185e0d4aec259cee1cbb3eba2edbc0..4d171600448bf44b1389d3ac25489519ecf6fd89 100644 GIT binary patch literal 1757 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K=!HtpAc7| z;Q#;sj~zSK-Q67;8ftEC4ix$N^(&CPfB$~JvNDi?3I20(-d9(DGv|jEiLVmrsn&A0A;)B zzkx!1B|(0{pg02o82$gh>Hj1DlUDuzKL;W~CsIlZWYJBj*3S$KEbg8zjv*Cu-p*kx znr$G$dQh!J`$>?@QTD>y*5U>?Bs}|gW~l$zZ9G@g;N+hDwbL{Ur-VjoE?>23&BC(G z^(OUtwpYFV&ObREA6FMRZR*ZBn}h?Z*Ik+0aJt~ftpgzra;gfAKR*XY{(OGkzf}3b zCyScQ1A-Hdb6Iq1c5M=Vu#cr{(L0te`i+Y+cxudDxOVt{Tix(heO`fh!MqQ};syKu z?cCP>kLyqNN6r^%#tIMeyTcu<=P)wXGXLQ|^N^+DTEjlZM%8Z_O!smQTx|k!uB*5G z)aBsV&u#Kq-p`?ew<2xE{{p6a84l+ASs5GI?mXMBaNvGJ-M_<}9kI-9Kl#-awlS9T zaO^Nm5IZhVkli54c;9xhW=6wGwu%Le%cKPM@NZB$(7cwd;>I$@_~3KzBquiHN_{Zx zoxVGLn}9+zvlv&!MLua>i+0{Osk{+d3K<8yn48#o)-WbAmq`g2e3;juQ@qS$3*+V0 zj?C`44dD&v4+LIk_{>|OX0w0pZ-#rUOw;>zu~{%VO}{5}p>9!u)lom7r70=A9PzhK zN)?pZ)jpcn`6sNK<%7?K*7PQm13}C`ZZ7BsItb*v1GNosrqqL^)r@i=mv3O(aU-jN zT`FM};~GZ2ZBh>!*)A~5=H2nXr{FoS1{M7}t>Lc$-@LV3*_LdW8lt1jJnv`vNslD$wHbc= z%mR5yQ=NjR@oYhZV=*dU|;TU|iYT4W>C9 z4zw{P)oBM+KfBE9@#bfLb=!2fA|&-35s?mA=j$t!p3Hfu3NZp%7HDvo*o0f3=bxR= z@s=56!F-_!w~Q0MpIOeT@@?7iT5M*{7Y8Ys$5rjfz?8$SVW+6jd-m$$pA8KnX5sy5 zUw;bUjIo_{_4)me_a13CGL$lyas;pkG!JD)a@>LXX=e)as{SO!fXY!%S3j3^P638$lZxy-8q?;K+cB%pAc6d z{r~^}W5%; zyu;JQF{EP7+dH{MvkgRA6D^mu$d=r3z4-V2GKW74i)w|W4zrj#s$6c zJGc+DTlik~WB4YLF{_U0$M2~RTVualF41YI`lH|QT4%fZf%k^nITa?_Co?b{;B-jh z`@lMZgMp!fDS>YTFje?7oMAL$V0gg!;IrIzhE4{C26cva%sC7eEDx^RgztX3m+{$G zy|UAS44W(yln3A>+@CF4aa~z~ zbAnLCb;|>P1wYh(diL3Y%ZYK4)N_aQmxrL&3b$4`dW}pFXKM;eM%5!|IkQWaLM1|VmTtAU7!)OzaQ9%q(V(dA&%5|;87DkF8E|;+gHJBz zOb_csZ&>^bW_Dpe@ayDy2JcIW?t)ShhY!`gZ9dEy9oyYJw z{;04#^VPhW%p#!N3jq$fhgl)424==-e?pg(oxbPpkb1uUjhG)OW21ou1`fIB>noH} zwiO`EK&WYD%&PuZ{6lzQF$+-e2KRz(=?8!YGE9yAvV$L?49aTw3slZ_Cir0rF!`7} zY-V?m?Ov^aj*r1qXWc%FqsQY5yjJVgAGH^~k+b T>=DmqP$+o1`njxgN@xNAR1(zO diff --git a/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png b/src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.png index 0d67dc66f99de93d718bd630d7c82e321eaa20af..c2f3e4ecf7f8b991c05d6f71c7ecd2b0fc020a8d 100644 GIT binary patch literal 1811 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K=!HtpAc7| z;Q#;sj~zSK-Q67;8ftEC4ix$N^(&CPfB$~JvNDi?3I20(-d9(DGv|jEiLVmrsn&A0A;)B zzkx!1B|(0{pg02o82$gh>Hj1DlUDuzKL;W~CsIlZWYJBj*3S$KEVZ64jv*Cu-p=7H zn(ZLqdQs?%XpJY|B9(H!*#b#Y=|{dvKij)12dj0ulBc0>20|4o6q~YUM=Cz`fo4#kCr#C`gfUg#yrM_4ZDDh9}Adg{R$Q^xX76MSCeCd^@7#^ zOPG?<4{Qd?b-Znu$HKBj)}XtXBg0xjlrdhmS?fi^5~~9Zd>*Tq)#fwvsVG!r+kO@M zy+&4G&$TPrRkIk)leeGkZn(jBVj4$8v3thE2IsR4oSv)r1UNSE$`rAk5lN8pSjp_e z%z2jKwnLO`f<%Op!s$b^XD;V6cIo9eXOy`^MAd_u}V8Vnjc8Lp&B@VM>FXVIRylHsPpwIMfZ-d=+gWVrb zUO&$&lKMBB>C`U)(a+Y_ldre0*wZxS@Qcu6NBLe&H?PaRDYtlY{M_ItZw;-^>))4F z__OAW4x?*Dhu6)o(|<`Uw0W;r@>pTvnwJenbq#)gULBK=ZFFw)R)+5>XWiAV?_jwS z`;YPPgJbHc&p1C6B!uWNGrRrWoU+5hKzr8f(+(O5amHZwuWdiV{x5hjQ@pwT`QC~+ zrdyml_WX0^mM}T+C$S=j@vnICY5PqLk5Us(?){*t@P}u{_Nfya7FBXY{nNR?&0)58 z@7f;LH7ra54Gb&_42&EO4cm(Zq3j!h4nHIf^0lMO8#e!)U(o6el4n3Dg)rCX9Ju|D z-`eRQ*K`aykcknI4cq_DzgynY#|YHgu$HCbHZx!NHn9h9mK`s~rsFpEhi&X<)@|Tq z5}2^9;kOu5jm$#1vusQ@AnMgual5{N{Z_-nTP@KSJ)b>L;X!gys!GgR~+$Zwx8 VwT?Zcq7_v7db;|#taD0e0s#HYniBv3 literal 1553 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5D>38$lZxy-8q?;K(=pyPlzi} z@c;k+$BrHA?(Pl^4K+762a0_C`V~mtzkk19SsBQ{1phfX@2jgnnml=DYU+P6F^B>+ zHMRGmqL_*YkI2cBCzmZ-wt4er8ae4l?8;1_(fK7oe!-w%1pyfS|G(+~Bma|D{r^7) zB0*j9(!$%om}CC#>EaktG3V`_+j)x(L|PLk1)P!&nc4p2uRi+;##wtOYDipT`|mxg z`_jykpOXt$s22r_^!mnLcMZHg)h2f0xAQB)Uu}83|AvXJ!_%7d=OMNSc0XccdiO*B z`Z87ygMX*DW-+#PUH`%)+pw4Q)TT;?n4_AfSF!)7TJkpZ`u$uX<~w#p^^7Zy+cW$r z+4-Hp?_Vh+LxT^)98(2-2KC(xHMP&CNgsHA|5kDxgFpr^2lE3K28JT01l|omWpfzz z%|9u2fRlmY2}?oSbB52Wzg}5?BYiI8v#rbGjD-%I&ATPfw;+OfLXmrh=z)dT8aS6Y z-(xz>P}4YvA*OK+gH2=4HHLVF^^y-b)-Y;t{Z13(JRlqHXM8|D!mHsy_JKJc*Y9OL z6Dz=Z;IYB<^EKQS4Bv|47|uO4UeCyOVE3Ln-XD9pT-XZq(@VI2O#jR{OHu-CAWtz&P(4uXoS=H(t_qjKPqvEhQsw1#KYx`s?0Q+(<9S(j(W5$G zc;8jja-NtLv-j z=+`|L=Qg)=)v>La$29rB-AUeQM)Pa8v2n~_^#4RkSG0re>HiZ73!hImI?bRYBVlT; z%$WYC+rUX?hN<;+#{*0{vw0Nx&di$oF8Aa0AMVX@6~-mqF zWp7Y!_{$TqMLYU@L&9(SZ(Q5qY7mSG5(>Be@mo7R!!3LMowd_(4xp9|q7GYZ6RK0Q z8xr!XY}gToKv@UAFxXJv7-SGCb?GM9T=YT@N)78&qol`;+0N{c(3IG5A From f43b4fc88837f83a0dfd3b7680ae36eb70aa655f Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Sun, 11 Feb 2024 17:06:11 +0000 Subject: [PATCH 6/9] feat: fusing machine functionality --- .../java/dev/ftb/ftbsba/tools/ToolsData.java | 8 + .../tools/content/core/EmittingEnergy.java | 59 +++ .../tools/content/core/EmittingFluidTank.java | 27 ++ .../content/core/EmittingStackHandler.java | 20 + .../content/core/FluidAndEnergyScreen.java | 175 +++++++++ .../FluidEnergyProcessorContainerData.java | 62 +++ .../content/core/FluidEnergyProvider.java | 17 + .../core/IOStackHandler.java} | 17 +- .../tools/content/core/ProgressProvider.java | 10 + .../content/fusion/FusingMachineBlock.java | 18 +- .../fusion/FusingMachineBlockEntity.java | 362 +++++++++++++++++- .../fusion/FusingMachineContainer.java | 59 ++- .../content/fusion/FusingMachineScreen.java | 56 ++- .../content/supercooler/SuperCoolerBlock.java | 17 + .../supercooler/SuperCoolerBlockEntity.java | 283 +++++++------- .../supercooler/SuperCoolerScreen.java | 176 ++------- .../tools/integration/jei/CrookCategory.java | 2 +- .../jei/FusingMachineCategory.java | 58 +++ .../tools/integration/jei/HammerCategory.java | 2 +- .../tools/integration/jei/JEIPlugin.java | 28 +- .../integration/jei/SuperCoolerCategory.java | 55 +++ .../kubejs/SuperCoolerRecipeSchema.java | 2 - .../FusingMachineRecipeSerializer.java | 2 +- .../recipies/SuperCoolerRecipeSerializer.java | 6 - 24 files changed, 1179 insertions(+), 342 deletions(-) create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingEnergy.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingStackHandler.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java rename src/main/java/dev/ftb/ftbsba/tools/{utils/IOStackWrapper.java => content/core/IOStackHandler.java} (72%) create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/ProgressProvider.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java index dca1361..4990e93 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java @@ -113,6 +113,9 @@ protected void addTranslations() { this.addBlock(ToolsRegistry.DIAMOND_AUTO_HAMMER, "Diamond Auto-hammer"); this.addBlock(ToolsRegistry.NETHERITE_AUTO_HAMMER, "Netherite Auto-hammer"); + this.addBlock(ToolsRegistry.FUSING_MACHINE, "Fusing Machine"); + this.addBlock(ToolsRegistry.SUPER_COOLER, "Super Cooler"); + this.add("screens.ftbsba.select_start_group", "Select a group"); this.add("screens.ftbsba.select_start", "Select a start"); this.add("screens.ftbsba.selected_start", "Selected start"); @@ -137,6 +140,11 @@ protected void addTranslations() { this.add("config.jade.plugin_ftbsba.blocks", "FTB Skyblock Addons Blocks"); this.add("container.ftbsba.super_cooler", "Super Cooler"); this.add("container.ftbsba.fusing_machine", "Fusing Machine"); + + this.add("ftbsba.jei.recipe.fusing", "Fusing"); + this.add("ftbsba.jei.recipe.super_cooler", "Super Cooler"); + this.add("ftbsba.jei.recipe.hammer", "Hammering"); + this.add("ftbsba.jei.recipe.crook", "Crooks"); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingEnergy.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingEnergy.java new file mode 100644 index 0000000..6f4c8c6 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingEnergy.java @@ -0,0 +1,59 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraft.util.Mth; +import net.minecraftforge.energy.EnergyStorage; + +import java.util.function.Consumer; + +public class EmittingEnergy extends EnergyStorage { + private final Consumer onChange; + + public EmittingEnergy(int capacity, Consumer onChange) { + super(capacity); + this.onChange = onChange; + } + + public EmittingEnergy(int capacity, int maxTransfer, Consumer onChange) { + super(capacity, maxTransfer); + this.onChange = onChange; + } + + public EmittingEnergy(int capacity, int maxReceive, int maxExtract, Consumer onChange) { + super(capacity, maxReceive, maxExtract); + this.onChange = onChange; + } + + public EmittingEnergy(int capacity, int maxReceive, int maxExtract, int energy, Consumer onChange) { + super(capacity, maxReceive, maxExtract, energy); + this.onChange = onChange; + } + + /** + * Only use when you need to override the energy value and bypass the maxReceive or maxExtract + * @param energy the energy value to override + */ + public void overrideEnergy(int energy) { + this.energy = Mth.clamp(energy, 0, capacity); + this.onChange.accept(this); + } + + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + var result = super.receiveEnergy(maxReceive, simulate); + if (!simulate) { + this.onChange.accept(this); + } + + return result; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + var result = super.extractEnergy(maxExtract, simulate); + if (!simulate) { + this.onChange.accept(this); + } + + return result; + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java new file mode 100644 index 0000000..b74d186 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java @@ -0,0 +1,27 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class EmittingFluidTank extends FluidTank { + private final Consumer onChange; + + public EmittingFluidTank(int capacity, Consumer onChange) { + super(capacity); + this.onChange = onChange; + } + + public EmittingFluidTank(int capacity, Predicate validator, Consumer onChange) { + super(capacity, validator); + this.onChange = onChange; + } + + @Override + protected void onContentsChanged() { + super.onContentsChanged(); + onChange.accept(this); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingStackHandler.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingStackHandler.java new file mode 100644 index 0000000..eeb7bbf --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingStackHandler.java @@ -0,0 +1,20 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraftforge.items.ItemStackHandler; + +import java.util.function.Consumer; + +public class EmittingStackHandler extends ItemStackHandler { + private final Consumer onChange; + + public EmittingStackHandler(int size, Consumer onChange) { + super(size); + this.onChange = onChange; + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + onChange.accept(this); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java new file mode 100644 index 0000000..dbaae5b --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java @@ -0,0 +1,175 @@ +package dev.ftb.ftbsba.tools.content.core; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; +import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL11; + +public abstract class FluidAndEnergyScreen extends AbstractContainerScreen { + private int fluidXOffset; + private int progressXOffset; + private ResourceLocation texture; + + public FluidAndEnergyScreen(T arg, Inventory arg2, Component arg3, int fluidXOffset, int progressXOffset, ResourceLocation texture) { + super(arg, arg2, arg3); + this.fluidXOffset = fluidXOffset; + this.progressXOffset = progressXOffset; + this.texture = texture; + } + + @Override + public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { + super.render(arg, mouseX, mouseY, partialTicks); + + if (mouseX > this.leftPos + this.fluidXOffset && mouseX < this.leftPos + this.fluidXOffset + 19 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { + arg.pushPose(); + arg.translate(mouseX - 5, mouseY, 600); + arg.scale(0.6F, 0.6F, 0F); + this.renderTooltip(arg, Component.literal(this.getFluidAmount() + " / " + this.getFluidCapacity() + " mB"), 0, 0); + arg.popPose(); + } + + if (mouseX > this.leftPos + 166 && mouseX < this.leftPos + 174 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { + MutableComponent energyText = Component.literal(this.getEnergyAmount() + " / " + this.getEnergyCapacity() + " FE"); + int width = this.font.width(energyText); + int scaledWidth = (int) (width * 0.6F); + arg.pushPose(); + arg.translate(mouseX - 10 - scaledWidth, mouseY, 600); + arg.scale(0.6F, 0.6F, 0F); + this.renderTooltip(arg, energyText, 0, 0); + arg.popPose(); + } + + renderTooltip(arg, mouseX, mouseY); + } + + @Override + protected void renderBg(PoseStack arg, float f, int i, int j) { + renderBackground(arg); + + arg.pushPose(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, this.texture); + + this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); + arg.popPose(); + + arg.pushPose(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 0.8F); + + // Energy + float x = (float) this.getEnergyAmount() / this.getEnergyCapacity(); + int energyHeight = (int) (x * 65); + this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4 + 65 - energyHeight, 197, 4 + 65 - energyHeight, 5, energyHeight); + arg.popPose(); + + RenderSystem.disableBlend(); + + var fluidStack = this.getFluidStack(); + if (fluidStack == null || fluidStack.getFluid() == null) { + return; + } + + var fluid = fluidStack.getFluid(); + var fluidExtensions = IClientFluidTypeExtensions.of(fluid); + var texture = fluidExtensions.getStillTexture(fluidStack); + var atlasSprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); + + // Fluid amount + float fluidHeight = (float) this.getFluidAmount() / this.getFluidCapacity() * 65; + int textureHeight = 16; + + int tilesRequired = (int) Math.ceil(fluidHeight / textureHeight); + + arg.pushPose(); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + int[] cols = decomposeColor(fluidExtensions.getTintColor(fluidStack)); + + for (int k = 0; k < tilesRequired; k++) { + int height = 16 - (int) Math.min(textureHeight, fluidHeight - k * textureHeight); + drawFluidTexture(arg, this.leftPos + (this.fluidXOffset + 1), this.topPos + 6 + 47 - (k * textureHeight), atlasSprite, height, cols); + } + + RenderSystem.disableBlend(); + arg.popPose(); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, this.texture); + + // Fluid gauge + arg.pushPose(); + arg.translate(0, 0, 101); + this.blit(arg, this.leftPos + (this.fluidXOffset + 1), this.topPos + 6, 178, 3, 18, 67); + arg.popPose(); + + // Finally, draw the progress bar + if (this.getProgressRequired() != 0) { + float computedPercentage = (float) this.getProgress() / this.getProgressRequired() * 24; + this.blit(arg, this.leftPos + this.progressXOffset, this.topPos + 28, 203, 0, (int) computedPercentage + 1, 16); + } + } + + // Thanks Des + private static void drawFluidTexture(PoseStack stack, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int[] cols) { + float uMin = textureSprite.getU0(); + float uMax = textureSprite.getU1(); + float vMin = textureSprite.getV0(); + float vMax = textureSprite.getV1(); + uMax = uMax - 0 / 16.0f * (uMax - uMin); + vMax = vMax - maskTop / 16.0f * (vMax - vMin); + + Matrix4f posMat = stack.last().pose(); + + Tesselator tessellator = Tesselator.getInstance(); + BufferBuilder worldrenderer = tessellator.getBuilder(); + worldrenderer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + worldrenderer.vertex(posMat, xCoord, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMax).endVertex(); + worldrenderer.vertex(posMat,xCoord + 16 - 0, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMax).endVertex(); + worldrenderer.vertex(posMat, xCoord + 16 - 0, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMin).endVertex(); + worldrenderer.vertex(posMat, xCoord, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMin).endVertex(); + tessellator.end(); + } + + // Thanks Des + public static int[] decomposeColor(int color) { + int[] res = new int[4]; + res[0] = color >> 24 & 0xff; + res[1] = color >> 16 & 0xff; + res[2] = color >> 8 & 0xff; + res[3] = color & 0xff; + return res; + } + + public abstract int getEnergyAmount(); + public abstract int getEnergyCapacity(); + + public abstract int getFluidAmount(); + public abstract int getFluidCapacity(); + + @Nullable + public abstract FluidStack getFluidStack(); + + public abstract int getProgress(); + public abstract int getProgressRequired(); +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java new file mode 100644 index 0000000..feb83b2 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java @@ -0,0 +1,62 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraft.world.inventory.ContainerData; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.loading.FMLEnvironment; + +/** + * Mostly borrowed from https://github.com/desht/ModularRouters/blob/MC1.20.1-master/src/main/java/me/desht/modularrouters/block/tile/ModularRouterBlockEntity.java#L1103-L1129 with permission. + * Thanks Desht! + */ +public class FluidEnergyProcessorContainerData implements ContainerData { + private final FluidEnergyProvider fluidEnergyProvider; + private final ProgressProvider progressProvider; + + public FluidEnergyProcessorContainerData(FluidEnergyProvider fluidEnergyProvider, ProgressProvider progressProvider) { + this.fluidEnergyProvider = fluidEnergyProvider; + this.progressProvider = progressProvider; + } + + @Override + public int get(int index) { + int result = 0; + + if (index == 0) { + result = this.fluidEnergyProvider.getEnergy() & 0x0000FFFF; + } else if (index == 1) { + result = (this.fluidEnergyProvider.getEnergy() & 0xFFFF0000) >> 16; + } else if (index == 2) { + return this.fluidEnergyProvider.getFluid(); + } else if (index == 3) { + return this.progressProvider.getProgress(); + } else if (index == 4) { + return this.progressProvider.getMaxProgress(); + } + + return result; + } + + @Override + public void set(int index, int value) { + if (value < 0) value += 65536; + final int finalValue = value; + + if (index == 0) { + this.fluidEnergyProvider.setEnergy(this.fluidEnergyProvider.getEnergy() & 0xFFFF0000 | finalValue); + } else if (index == 1) { + this.fluidEnergyProvider.setEnergy(this.fluidEnergyProvider.getEnergy() & 0x0000FFFF | (finalValue << 16)); + } else if (index == 2) { + this.fluidEnergyProvider.setFluid(finalValue); + } else if (index == 3) { + this.progressProvider.setProgress(finalValue); + } else if (index == 4) { + this.progressProvider.setMaxProgress(finalValue); + } + } + + @Override + public int getCount() { + return 5; + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java new file mode 100644 index 0000000..5dffef8 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java @@ -0,0 +1,17 @@ +package dev.ftb.ftbsba.tools.content.core; + +public interface FluidEnergyProvider { + int getEnergy(); + int getMaxEnergy(); + + int getFluid(); + int getMaxFluid(); + + void setFluid(int fluid); + + void setEnergy(int energy); + + void setProgress(int progress); + + void setMaxProgress(int maxProgress); +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java similarity index 72% rename from src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java rename to src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java index ae3ab06..4fb847e 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/utils/IOStackWrapper.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java @@ -1,17 +1,19 @@ -package dev.ftb.ftbsba.tools.utils; +package dev.ftb.ftbsba.tools.content.core; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; -public class IOStackWrapper implements IItemHandler { +import java.util.function.BiConsumer; + +public class IOStackHandler implements IItemHandler { ItemStackHandler input; ItemStackHandler output; - public IOStackWrapper(ItemStackHandler input, ItemStackHandler output) { - this.input = input; - this.output = output; + public IOStackHandler(int inputSlots, int outputSlots, BiConsumer onChange) { + this.input = new EmittingStackHandler(inputSlots, (contents) -> onChange.accept(this, IO.INPUT)); + this.output = new EmittingStackHandler(outputSlots, (contents) -> onChange.accept(this, IO.OUTPUT)); } @Override @@ -51,4 +53,9 @@ public ItemStackHandler getInput() { public ItemStackHandler getOutput() { return output; } + + public enum IO { + INPUT, + OUTPUT + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/ProgressProvider.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/ProgressProvider.java new file mode 100644 index 0000000..93c6555 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/ProgressProvider.java @@ -0,0 +1,10 @@ +package dev.ftb.ftbsba.tools.content.core; + +public interface ProgressProvider { + int getProgress(); + int getMaxProgress(); + + void setProgress(int progress); + + void setMaxProgress(int maxProgress); +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java index 6daee99..5df6ca4 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java @@ -28,7 +28,7 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player return InteractionResult.SUCCESS; } - NetworkHooks.openScreen((ServerPlayer) player, (FusingMachineBlockEntity) level.getBlockEntity(pos)); + NetworkHooks.openScreen((ServerPlayer) player, (FusingMachineBlockEntity) level.getBlockEntity(pos), pos); return InteractionResult.SUCCESS; } @@ -43,4 +43,20 @@ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { return FusingMachineBlockEntity::ticker; } + + @Override + public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) { + super.onRemove(arg, arg2, arg3, arg4, bl); + + BlockEntity entity = arg2.getBlockEntity(arg3); + if (!(entity instanceof FusingMachineBlockEntity fusingBlockEntity)) { + return; + } + + fusingBlockEntity.input.ifPresent(handler -> { + for (int i = 0; i < handler.getSlots(); i++) { + Block.popResource(arg2, arg3, handler.getStackInSlot(i)); + } + }); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java index e93f5b5..4ce1e3e 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java @@ -1,36 +1,390 @@ package dev.ftb.ftbsba.tools.content.fusion; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.core.*; +import dev.ftb.ftbsba.tools.recipies.FusingMachineRecipe; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.templates.FluidTank; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class FusingMachineBlockEntity extends BlockEntity implements MenuProvider { +import javax.swing.*; +import java.util.List; +import java.util.function.Consumer; + +public class FusingMachineBlockEntity extends BlockEntity implements MenuProvider, FluidEnergyProvider, ProgressProvider { + public LazyOptional energy = LazyOptional.of(() -> new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged())); + public LazyOptional tank = LazyOptional.of(() -> new ExtractOnlyFluidTank(10000, (tank) -> this.setChanged())); + public LazyOptional input = LazyOptional.of(() -> new EmittingStackHandler(2, (contents) -> { + this.setChanged(); + this.progress = 0; + })); + + public int progress = 0; + public int progressRequired = 0; + + public FusingMachineRecipe currentRecipe = null; + + FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); + public FusingMachineBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.FUSING_MACHINE_BLOCK_ENTITY.get(), pos, state); } public static void ticker(Level level, BlockPos pos, BlockState state, T t) { - if (t instanceof FusingMachineBlockEntity entity) { -// System.out.println("FusingMachineBlockEntity.ticker"); + if (!(t instanceof FusingMachineBlockEntity entity)) { + return; + } + + if (level.isClientSide) { + return; + } + + // Requires input items, energy and the fluid tank to be not full and the correct fluid for the recipe + if (!entity.hasEnergy() || !entity.hasOccupiedInputSlots()) { + return; + } + + // We need to find the recipe before we can check the fluid tank + if (entity.progress == 0) { + var recipe = entity.testForRecipe(); + if (recipe == null) { + return; + } + + // Test for tank validity + // TODO: Add fluid check + var tank = entity.tank.orElseThrow(RuntimeException::new); + if (!tank.isEmpty() && !tank.getFluid().isFluidEqual(recipe.fluidResult)) { + return; + } + + // Otherwise the fluid is either empty or the same as the recipe + if (!tank.isEmpty() && tank.getFluid().getAmount() + recipe.fluidResult.getAmount() > tank.getCapacity()) { + // Don't allow the fluid to overflow + return; + } + + // Finally, we can start the process + entity.progressRequired = recipe.energyComponent.ticksToProcess(); + entity.progress = 1; // Start the progress + entity.currentRecipe = recipe; + } + + if (entity.currentRecipe != null) { + if (entity.progress == entity.progressRequired) { + // We're done... Ouput the result + entity.extractRecipe(); + entity.breakProgress(); + } else { + entity.useEnergy(); + entity.progress ++; + } + } + } + + //#region BlockEntity processing + + private void extractRecipe() { + var inventory = input.orElseThrow(RuntimeException::new); + var tank = this.tank.orElseThrow(RuntimeException::new); + + var requiredItems = this.currentRecipe.ingredients; + // Try and remove the items from the input slots + for (var ingredient : requiredItems) { + for (int i = 0; i < inventory.getSlots(); i++) { + var stack = inventory.getStackInSlot(i); + if (ingredient.test(stack)) { + var result = inventory.extractItem(i, 1, true); + if (result.isEmpty()) { + breakProgress(); + return; + } + } + } } + + for (var ingredient : requiredItems) { + for (int i = 0; i < inventory.getSlots(); i++) { + var stack = inventory.getStackInSlot(i); + if (ingredient.test(stack)) { + // This logically can't be false due to the simulation above + inventory.extractItem(i, 1, false); + } + } + } + + tank.forceFill(this.currentRecipe.fluidResult, IFluidHandler.FluidAction.EXECUTE); + } + + private void useEnergy() { + if (this.currentRecipe == null) { + return; + } + + if (!this.energy.isPresent()) { + breakProgress(); + return; + } + + EmittingEnergy emittingEnergy = this.energy.orElseThrow(RuntimeException::new); + var result = emittingEnergy.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), true); + if (result < this.currentRecipe.energyComponent.fePerTick()) { + breakProgress(); + return; + } + + emittingEnergy.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), false); + } + + private void breakProgress() { + this.progress = 0; + this.progressRequired = 0; + this.currentRecipe = null; } + private boolean hasEnergy() { + return energy.map(EmittingEnergy::getEnergyStored).orElse(0) > 0; + } + + private boolean hasOccupiedInputSlots() { + if (!input.isPresent()) { + return false; + } + + var hasItems = false; + var handler = input.orElseThrow(RuntimeException::new); + + for (int i = 0; i < handler.getSlots(); i++) { + if (!handler.getStackInSlot(i).isEmpty()) { + hasItems = true; + break; + } + } + + return hasItems; + } + + @Nullable + private FusingMachineRecipe testForRecipe() { + if (!input.isPresent()) { + return null; + } + + + var handler = input.orElseThrow(RuntimeException::new); + + // This is an immutable hash map so the lookup is fast + var recipes = level.getRecipeManager().getAllRecipesFor(ToolsRegistry.FUSING_MACHINE_RECIPE_TYPE.get()); + + if (recipes.isEmpty()) { + return null; + } + + for (var recipe : recipes) { + List ingredients = recipe.ingredients.stream().filter(ingredient -> !ingredient.isEmpty()).toList(); + + NonNullList foundItems = NonNullList.create(); + for (int i = 0; i < handler.getSlots(); i++) { + if (handler.getStackInSlot(i).isEmpty()) { + // Don't waste time checking empty slots + continue; + } + + for (Ingredient ingredient : ingredients) { + if (ingredient.test(handler.getStackInSlot(i))) { + foundItems.add(ingredient); + } + } + } + + for (var ingredient : recipe.ingredients) { + if (!foundItems.contains(ingredient)) { + return null; + } + } + + return recipe; + } + + return null; + } + + //#endregion + + //#region BlockEntity setup and syncing + @Override public Component getDisplayName() { return Component.translatable("container.ftbsba.fusing_machine"); // TODO: Add translation } + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) { + return input.cast(); + } else if (cap == ForgeCapabilities.ENERGY) { + return energy.cast(); + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + return tank.cast(); + } + + return super.getCapability(cap, side); + } + @Nullable @Override public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { - return new FusingMachineContainer(i, arg, arg2); + return new FusingMachineContainer(i, containerData, arg, arg2, this); + } + + @Override + public void load(CompoundTag arg) { + super.load(arg); + + input.ifPresent(input -> input.deserializeNBT(arg.getCompound("input"))); + energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); + tank.ifPresent(tank -> tank.readFromNBT(arg.getCompound("fluid"))); + } + + @Override + protected void saveAdditional(CompoundTag arg) { + super.saveAdditional(arg); + + input.ifPresent(input -> arg.put("input",input.serializeNBT())); + energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); + tank.ifPresent(tank -> arg.put("fluid", tank.writeToNBT(new CompoundTag()))); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + input.invalidate(); + energy.invalidate(); + tank.invalidate(); + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this, entity -> this.getUpdateTag()); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag compoundTag = new CompoundTag(); + saveAdditional(compoundTag); + return compoundTag; + } + + + @Override + public void handleUpdateTag(CompoundTag tag) { + load(tag); + } + + @Override + public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { + load(pkt.getTag()); + } + + //#endregion + + //#region Data Syncing helper methods + + @Override + public int getEnergy() { + return energy.map(EmittingEnergy::getEnergyStored).orElse(0); + } + + @Override + public int getMaxEnergy() { + return energy.map(EmittingEnergy::getMaxEnergyStored).orElse(0); + } + + @Override + public int getFluid() { + return tank.map(IFluidTank::getFluidAmount).orElse(0); + } + + @Override + public int getMaxFluid() { + return tank.map(IFluidTank::getCapacity).orElse(0); + } + + @Override + public void setFluid(int fluid) { + tank.ifPresent(t -> t.overrideFluidAmount(fluid)); + } + + @Override + public void setEnergy(int energy) { + this.energy.ifPresent(e -> e.overrideEnergy(energy)); + } + + @Override + public int getProgress() { + return progress; + } + + @Override + public int getMaxProgress() { + return progressRequired; + } + + @Override + public void setProgress(int progress) { + this.progress = progress; + } + + @Override + public void setMaxProgress(int maxProgress) { + this.progressRequired = maxProgress; + } + + //#endregion + + public static class ExtractOnlyFluidTank extends EmittingFluidTank { + public ExtractOnlyFluidTank(int capacity, Consumer listener) { + super(capacity, listener); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return 0; + } + + public int forceFill(FluidStack resource, FluidAction action) { + return super.fill(resource, action); + } + + public void overrideFluidAmount(int amount) { + if (this.fluid.isEmpty()) { + return; + } + + this.fluid.setAmount(amount); + } } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java index 461a7b9..cea8eb4 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java @@ -1,39 +1,88 @@ package dev.ftb.ftbsba.tools.content.fusion; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerBlockEntity; import net.minecraft.client.gui.screens.inventory.ContainerScreen; +import net.minecraft.core.Vec3i; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.SlotItemHandler; import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; public class FusingMachineContainer extends AbstractContainerMenu { - protected FusingMachineContainer(int i, Inventory arg, Player arg2) { + FusingMachineBlockEntity entity; + ContainerData containerData; + + protected FusingMachineContainer(int i, ContainerData data, Inventory arg, Player arg2, FusingMachineBlockEntity entity) { super(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), i); addPlayerSlots(arg, 8, 56, this::addSlot); + this.entity = entity; + this.entity.input.ifPresent(itemHandler -> { + addSlot(new SlotItemHandler(itemHandler, 0, 43, 27)); + addSlot(new SlotItemHandler(itemHandler, 1, 43 + 18, 27)); + }); + + this.containerData = data; + addDataSlots(data); } public FusingMachineContainer(int i, Inventory arg, FriendlyByteBuf arg2) { - this(i, arg, arg.player); + this(i, arg, arg.player, (FusingMachineBlockEntity) arg.player.level.getBlockEntity(arg2.readBlockPos())); + } + + public FusingMachineContainer(int i, Inventory arg, Player player, FusingMachineBlockEntity entity) { + this(i, entity.containerData, arg, player, entity); } @Override - public ItemStack quickMoveStack(Player arg, int i) { - return null; + public ItemStack quickMoveStack(Player arg, int index) { + ItemStack itemstack = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack currentStack = slot.getItem(); + itemstack = currentStack.copy(); + + if (index > 35) { + if (!this.moveItemStackTo(currentStack, 0, 36, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(currentStack, 36, 38, false)) { + return ItemStack.EMPTY; + } + + if (currentStack.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + + return itemstack; } @Override public boolean stillValid(Player arg) { - return true; + Vec3 position = arg.position(); + return this.entity.getBlockPos().distManhattan(new Vec3i(position.x, position.y, position.z)) <= 8; + } + + @Override + public void slotsChanged(Container arg) { + super.slotsChanged(arg); + this.entity.setChanged(); } public static void addPlayerSlots(Inventory playerInventory, int inX, int inY, Consumer addSlot) { diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java index 4aa2816..2116a91 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java @@ -1,37 +1,65 @@ package dev.ftb.ftbsba.tools.content.fusion; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import dev.ftb.ftbsba.FTBSBA; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.GameRenderer; +import dev.ftb.ftbsba.tools.content.core.FluidAndEnergyScreen; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import org.jetbrains.annotations.Nullable; -public class FusingMachineScreen extends AbstractContainerScreen { +public class FusingMachineScreen extends FluidAndEnergyScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/fusing_machine_background.png"); public FusingMachineScreen(FusingMachineContainer arg, Inventory arg2, Component arg3) { - super(arg, arg2, arg3); + super(arg, arg2, arg3, 140, 90, TEXTURE); +// this.titleLabelX = 96; } @Override - protected void init() { - super.init(); + protected void renderLabels(PoseStack arg, int i, int j) { + arg.pushPose(); + arg.scale(0.75F, 0.75F, 0.75F); + this.font.draw(arg, this.title, (float)this.titleLabelX, (float)this.titleLabelY, 4210752); + arg.popPose(); } @Override - public void render(PoseStack arg, int m, int n, float g) { - super.render(arg, m, n, g); + public int getEnergyAmount() { + var data = this.menu.containerData; + return (data.get(0) & 0xFFFF) | (data.get(1) << 16); } @Override - protected void renderBg(PoseStack arg, float f, int i, int j) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShaderTexture(0, TEXTURE); + public int getEnergyCapacity() { + return this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); + } + + @Override + public int getFluidAmount() { + return this.menu.containerData.get(2); + } + + @Override + public int getFluidCapacity() { + return this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); + } - this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); + @Override + public @Nullable FluidStack getFluidStack() { + return this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); + } + + @Override + public int getProgress() { + return this.menu.containerData.get(3); + } + + @Override + public int getProgressRequired() { + return this.menu.containerData.get(4); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java index 7f2c91c..36344a0 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java @@ -1,5 +1,6 @@ package dev.ftb.ftbsba.tools.content.supercooler; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; @@ -43,4 +44,20 @@ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { return SuperCoolerBlockEntity::ticker; } + + @Override + public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) { + super.onRemove(arg, arg2, arg3, arg4, bl); + + BlockEntity entity = arg2.getBlockEntity(arg3); + if (!(entity instanceof SuperCoolerBlockEntity superCoolerEntity)) { + return; + } + + superCoolerEntity.ioWrapper.ifPresent(handler -> { + for (int i = 0; i < handler.getSlots(); i++) { + Block.popResource(arg2, arg3, handler.getStackInSlot(i)); + } + }); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index 8e5f871..9f56fcf 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -1,8 +1,8 @@ package dev.ftb.ftbsba.tools.content.supercooler; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.core.*; import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; -import dev.ftb.ftbsba.tools.utils.IOStackWrapper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; @@ -10,19 +10,20 @@ import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.EnergyStorage; +import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -30,94 +31,29 @@ import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - -public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider { - public ItemStackHandler inventory = new ItemStackHandler(3) { - @Override - protected void onContentsChanged(int slot) { - setChanged(); - if (progress > 0) { - progress = 0; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider, ProgressProvider, FluidEnergyProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(SuperCoolerBlockEntity.class); + + public LazyOptional energy = LazyOptional.of(() -> new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged())); + public LazyOptional tank = LazyOptional.of(() -> new EmittingFluidTank(10000, (tank) -> this.setChanged())); + public LazyOptional ioWrapper = LazyOptional.of(() -> new IOStackHandler(3, 1, (container, ioType) -> { + setChanged(); + if (ioType == IOStackHandler.IO.INPUT) { + if (this.progress > 0) { + this.progress = 0; } } - }; - - public ItemStackHandler output = new ItemStackHandler(1) { - @Override - protected void onContentsChanged(int slot) { - setChanged(); - } - }; - - public CustomEnergy energy = new CustomEnergy(this); - public LazyOptional energyLazy = LazyOptional.of(() -> energy); - - public LazyOptional tank = LazyOptional.of(() -> new FluidTank(10000) { - @Override - protected void onContentsChanged() { - setChanged(); - } - }); - - public LazyOptional ioWrapper = LazyOptional.of(() -> new IOStackWrapper(inventory, output)); + })); - /** - * Mostly borrowed from https://github.com/desht/ModularRouters/blob/MC1.20.1-master/src/main/java/me/desht/modularrouters/block/tile/ModularRouterBlockEntity.java#L1103-L1129 with permission. - * Thanks Desht! - */ - ContainerData containerData = new ContainerData() { - @Override - public int get(int index) { - int result = 0; - if (index == 0) { - result = energy.getEnergyStored() & 0x0000FFFF; - } else if (index == 1) { - result = (energy.getEnergyStored() & 0xFFFF0000) >> 16; - } else if (index == 2) { - return tank.map(IFluidTank::getFluid).map(FluidStack::getAmount).orElse(0); - } else if (index == 3) { - return progress; - } else if (index == 4) { - return progressRequired; - } - - return result; - } - - @Override - public void set(int index, int value) { - if (value < 0) value += 65536; - - if (index == 0) { - energy.setEnergy(energy.getEnergyStored() & 0xFFFF0000 | value, false); - } else if (index == 1) { - energy.setEnergy(energy.getEnergyStored() & 0x0000FFFF | (value << 16), false); - } else if (index == 2) { - final int finalValue = value; - tank.ifPresent(tank -> { - // If the value is greater than the previous value, we're filling the tank - if (finalValue > tank.getFluidAmount()) { - tank.fill(new FluidStack(tank.getFluid(), finalValue - tank.getFluidAmount()), IFluidHandler.FluidAction.EXECUTE); - } else { - tank.drain(tank.getFluidAmount() - finalValue, IFluidHandler.FluidAction.EXECUTE); - } - }); - } else if (index == 3) { - progress = value; - } else if (index == 4) { - progressRequired = value; - } - } - - @Override - public int getCount() { - return 5; - } - }; + FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); int progress = 0; int progressRequired = 0; SuperCoolerRecipe processingRecipe = null; + boolean tickLock = false; public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); @@ -128,7 +64,7 @@ public static void ticker(Level level, BlockPos pos, Blo return; } - if (level.isClientSide) { + if (level.isClientSide || entity.tickLock) { return; } @@ -151,17 +87,25 @@ public static void ticker(Level level, BlockPos pos, Blo entity.progress = 1; entity.processingRecipe = recipe; entity.progressRequired = recipe.energyComponent.ticksToProcess(); - } else if (entity.progress >= entity.progressRequired) { - entity.executeRecipe(); - entity.breakProgress(); - } else { - // Use energy - entity.useEnergy(); - entity.progress++; + } + + if (entity.processingRecipe != null) { + if (entity.progress == entity.progressRequired) { + entity.executeRecipe(); + } else { + // Use energy + entity.useEnergy(); + entity.progress++; + } } } public void executeRecipe() { + if (this.processingRecipe == null) { + breakProgress(); + return; + } + // This shouldn't be possible, but we'll check because we have to var tank = this.tank.orElseThrow(RuntimeException::new); var ioWrapper = this.ioWrapper.orElseThrow(RuntimeException::new); @@ -204,6 +148,7 @@ public void executeRecipe() { // Produce the result ioWrapper.getOutput().insertItem(0, this.processingRecipe.result.copy(), false); + breakProgress(); } private void useEnergy() { @@ -211,13 +156,19 @@ private void useEnergy() { return; } - var result = this.energy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), true); + if (!this.energy.isPresent()) { + breakProgress(); + return; + } + + EmittingEnergy emittingEnergy = this.energy.orElseThrow(RuntimeException::new); + var result = emittingEnergy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), true); if (result < this.processingRecipe.energyComponent.fePerTick()) { breakProgress(); return; } - this.energy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), false); + emittingEnergy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), false); } /** @@ -227,6 +178,7 @@ private void breakProgress() { this.progress = 0; this.progressRequired = 0; this.processingRecipe = null; + this.tickLock = false; } public boolean canAcceptOutput(SuperCoolerRecipe recipe) { @@ -251,7 +203,7 @@ private boolean hasFluid() { } private boolean hasEnergy() { - return energy.getEnergyStored() > 0; + return energy.map(IEnergyStorage::getEnergyStored).orElse(0) > 0; } private boolean hasItemInAnySlot() { @@ -275,7 +227,7 @@ private boolean hasItemInAnySlot() { */ @Nullable private SuperCoolerRecipe testForRecipe() { - LazyOptional ioWrapper = this.ioWrapper; + LazyOptional ioWrapper = this.ioWrapper; if (!ioWrapper.isPresent()) { return null; } @@ -290,9 +242,14 @@ private SuperCoolerRecipe testForRecipe() { return null; } + if (!this.ioWrapper.isPresent()) { + return null; + } + + var io = ioWrapper.orElseThrow(RuntimeException::new); boolean hasOccupiedSlot = false; - for (int i = 0; i < this.inventory.getSlots(); i++) { - if (!this.inventory.getStackInSlot(i).isEmpty()) { + for (int i = 0; i < io.getInput().getSlots(); i++) { + if (!io.getInput().getStackInSlot(i).isEmpty()) { hasOccupiedSlot = true; break; } @@ -310,11 +267,9 @@ private SuperCoolerRecipe testForRecipe() { .toList(); for (var recipe : recipesForFluid) { - IOStackWrapper io = ioWrapper.orElseThrow(RuntimeException::new); ItemStackHandler input = io.getInput(); var filledIngredients = recipe.ingredients.stream().filter(e -> !e.isEmpty()).toList(); - System.out.println(filledIngredients.size()); NonNullList foundIngredients = NonNullList.create(); for (int i = 0; i < input.getSlots(); i++) { @@ -348,7 +303,7 @@ private SuperCoolerRecipe testForRecipe() { if (cap == ForgeCapabilities.ITEM_HANDLER) { return ioWrapper.cast(); } else if (cap == ForgeCapabilities.ENERGY) { - return energyLazy.cast(); + return energy.cast(); } else if (cap == ForgeCapabilities.FLUID_HANDLER) { return tank.cast(); } @@ -358,7 +313,7 @@ private SuperCoolerRecipe testForRecipe() { @Override public Component getDisplayName() { - return Component.translatable("container.ftbsba.super_cooler"); // TODO: Add translation + return Component.translatable("container.ftbsba.super_cooler"); } @Nullable @@ -371,7 +326,7 @@ public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { public void invalidateCaps() { super.invalidateCaps(); ioWrapper.invalidate(); - energyLazy.invalidate(); + energy.invalidate(); tank.invalidate(); } @@ -383,10 +338,32 @@ public void load(CompoundTag arg) { wrapper.getInput().deserializeNBT(arg.getCompound("input")); wrapper.getInput().deserializeNBT(arg.getCompound("output")); }); - energyLazy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); - tank.ifPresent(tank -> { - ((FluidTank) tank).readFromNBT(arg.getCompound("fluid")); - }); + energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); + tank.ifPresent(tank -> ((FluidTank) tank).readFromNBT(arg.getCompound("fluid"))); + + // Write the progress + this.progress = arg.getInt("progress"); + this.progressRequired = arg.getInt("progressRequired"); + + // Write the recipe id + if (arg.contains("recipe")) { + try { + Recipe parsedRecipe = this.level.getServer().getRecipeManager().byKey(new ResourceLocation(arg.getString("recipe"))).orElse(null); + if (parsedRecipe == null) { + this.processingRecipe = null; + this.progress = 0; + this.progressRequired = 0; + return; + } + + this.processingRecipe = (SuperCoolerRecipe) parsedRecipe; // Try catch just in case + } catch (Exception e) { + LOGGER.error("Failed to load recipe from NBT", e); + this.processingRecipe = null; + this.progress = 0; + this.progressRequired = 0; + } + } } @Override @@ -397,10 +374,17 @@ protected void saveAdditional(CompoundTag arg) { arg.put("input", wrapper.getInput().serializeNBT()); arg.put("output", wrapper.getInput().serializeNBT()); }); - energyLazy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); - tank.ifPresent(tank -> { - arg.put("fluid", ((FluidTank) tank).writeToNBT(new CompoundTag())); - }); + energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); + tank.ifPresent(tank -> arg.put("fluid", ((FluidTank) tank).writeToNBT(new CompoundTag()))); + + // Write the progress + arg.putInt("progress", this.progress); + arg.putInt("progressRequired", this.progressRequired); + + // Write the recipe id + if (this.processingRecipe != null) { + arg.putString("recipe", this.processingRecipe.getId().toString()); + } } @Override @@ -426,37 +410,60 @@ public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { load(pkt.getTag()); } - public static class CustomEnergy extends EnergyStorage { - BlockEntity entity; + @Override + public int getEnergy() { + return energy.map(IEnergyStorage::getEnergyStored).orElse(0); + } - public CustomEnergy(BlockEntity blockEntity) { - super(100000, 1000, 1000); - entity = blockEntity; + @Override + public int getMaxEnergy() { + return energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); + } - } - @Override - public int receiveEnergy(int maxReceive, boolean simulate) { - var result = super.receiveEnergy(maxReceive, simulate); - if (!simulate) { - this.entity.setChanged(); - } - return result; - } + @Override + public int getFluid() { + return tank.map(IFluidTank::getFluid).map(FluidStack::getAmount).orElse(0); + } - @Override - public int extractEnergy(int maxExtract, boolean simulate) { - var result = super.extractEnergy(maxExtract, simulate); - if (!simulate) { - this.entity.setChanged(); - } - return result; - } + @Override + public int getMaxFluid() { + return tank.map(IFluidTank::getCapacity).orElse(0); + } - public void setEnergy(int energy, boolean update) { - this.energy = energy; - if (update) { - this.entity.setChanged(); + @Override + public void setEnergy(int energy) { + this.energy.ifPresent(e -> e.overrideEnergy(energy)); + } + + @Override + public void setFluid(int fluid) { + this.tank.ifPresent(t -> { + var stack = new FluidStack(t.getFluid().getFluid(), fluid); + if (stack.getAmount() > t.getFluidAmount()) { + t.fill(stack, IFluidHandler.FluidAction.EXECUTE); + } else { + t.drain(t.getFluidAmount() - stack.getAmount(), IFluidHandler.FluidAction.EXECUTE); } - } + }); + } + + @Override + public int getProgress() { + return progress; + } + + @Override + public int getMaxProgress() { + return progressRequired; + } + + @Override + public void setProgress(int progress) { + this.progress = progress; + } + + @Override + public void setMaxProgress(int maxProgress) { + this.progressRequired = maxProgress; } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java index 3d57a9a..40a7658 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java @@ -1,175 +1,65 @@ package dev.ftb.ftbsba.tools.content.supercooler; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.*; -import com.mojang.math.Matrix4f; +import com.mojang.blaze3d.vertex.PoseStack; import dev.ftb.ftbsba.FTBSBA; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import dev.ftb.ftbsba.tools.content.core.FluidAndEnergyScreen; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.AbstractFurnaceMenu; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; -import org.lwjgl.opengl.GL11; +import org.jetbrains.annotations.Nullable; -public class SuperCoolerScreen extends AbstractContainerScreen { +public class SuperCoolerScreen extends FluidAndEnergyScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/super_cooler_background.png"); public SuperCoolerScreen(SuperCoolerContainer arg, Inventory arg2, Component arg3) { - super(arg, arg2, arg3); + super(arg, arg2, arg3, 3, 79, TEXTURE); this.titleLabelX = 96; - } @Override - public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { - super.render(arg, mouseX, mouseY, partialTicks); + protected void renderLabels(PoseStack arg, int i, int j) { + arg.pushPose(); + arg.scale(0.75F, 0.75F, 0.75F); + this.font.draw(arg, this.title, (float)this.titleLabelX, (float)this.titleLabelY, 4210752); + arg.popPose(); + } + @Override + public int getEnergyAmount() { var data = this.menu.containerData; - if (mouseX > this.leftPos + 3 && mouseX < this.leftPos + 21 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { - arg.pushPose(); - arg.translate(mouseX - 5, mouseY, 600); - arg.scale(0.6F, 0.6F, 0F); - this.renderTooltip(arg, Component.literal(data.get(2) + " / " + this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0) + " mB"), 0, 0); - arg.popPose(); - } - - if (mouseX > this.leftPos + 166 && mouseX < this.leftPos + 174 && mouseY > this.topPos + 3 && mouseY < this.topPos + 5 + 65) { - var uncompressedEnergy = (data.get(0) & 0xFFFF) | (data.get(1) << 16); - - MutableComponent energyText = Component.literal(uncompressedEnergy + " / " + this.menu.entity.energyLazy.map(IEnergyStorage::getMaxEnergyStored).orElse(0) + " FE"); - int width = this.font.width(energyText); - int scaledWidth = (int) (width * 0.6F); - arg.pushPose(); - arg.translate(mouseX - 10 - scaledWidth, mouseY, 600); - arg.scale(0.6F, 0.6F, 0F); - this.renderTooltip(arg, energyText, 0, 0); - arg.popPose(); - } - - renderTooltip(arg, mouseX, mouseY); + return (data.get(0) & 0xFFFF) | (data.get(1) << 16); } @Override - protected void renderBg(PoseStack arg, float f, int i, int j) { - renderBackground(arg); - - arg.pushPose(); - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShaderTexture(0, TEXTURE); - - this.blit(arg, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); - arg.popPose(); - - var data = this.menu.entity.containerData; - - int combinedInt = data.get(0) & 0xFFFF | (data.get(1) & 0xFFFF) << 16; - int energyMax = this.menu.entity.energyLazy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); - int fluidMax = this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); - - arg.pushPose(); - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 0.8F); - - // Energy - float x = (float) combinedInt / energyMax; - int energyHeight = (int) (x * 65); - this.blit(arg, this.leftPos + imageWidth - 9, this.topPos + 4 + 65 - energyHeight, 197, 4 + 65 - energyHeight, 5, energyHeight); - arg.popPose(); - - RenderSystem.disableBlend(); - - var fluid = this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); - if (fluid == null) { - return; - } - - var fluidExtensions = IClientFluidTypeExtensions.of(fluid.getFluid()); - var texture = fluidExtensions.getStillTexture(fluid); - var atlasSprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); - - // Fluid amount - float fluidHeight = (float) data.get(2) / fluidMax * 65; - int textureHeight = 16; - - int tilesRequired = (int) Math.ceil(fluidHeight / textureHeight); - - arg.pushPose(); - RenderSystem.setShader(GameRenderer::getPositionColorTexShader); - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); - RenderSystem.enableBlend(); - RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - - int[] cols = decomposeColor(fluidExtensions.getTintColor(fluid)); - - for (int k = 0; k < tilesRequired; k++) { - int height = 16 - (int) Math.min(textureHeight, fluidHeight - k * textureHeight); - drawFluidTexture(arg, this.leftPos + 4, this.topPos + 6 + 47 - (k * textureHeight), atlasSprite, height, cols); - } - - RenderSystem.disableBlend(); - arg.popPose(); - - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, TEXTURE); - - // Fluid gauge - arg.pushPose(); - arg.translate(0, 0, 101); - this.blit(arg, this.leftPos + 4, this.topPos + 6, 178, 3, 18, 67); - arg.popPose(); - - // Finally, draw the progress bar - float computedPercentage = data.get(4) == 0 ? 0 : (float) data.get(3) / data.get(4) * 24; - this.blit(arg, this.leftPos + 80, this.topPos + 28, 203, 0, (int) computedPercentage + 1, 16); + public int getEnergyCapacity() { + return this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); } - private static void drawFluidTexture(PoseStack stack, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int[] cols) { - float uMin = textureSprite.getU0(); - float uMax = textureSprite.getU1(); - float vMin = textureSprite.getV0(); - float vMax = textureSprite.getV1(); - uMax = uMax - 0 / 16.0f * (uMax - uMin); - vMax = vMax - maskTop / 16.0f * (vMax - vMin); + @Override + public int getFluidAmount() { + return this.menu.containerData.get(2); + } - Matrix4f posMat = stack.last().pose(); + @Override + public int getFluidCapacity() { + return this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); + } - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder worldrenderer = tessellator.getBuilder(); - worldrenderer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); - worldrenderer.vertex(posMat, xCoord, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMax).endVertex(); - worldrenderer.vertex(posMat,xCoord + 16 - 0, yCoord + 16, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMax).endVertex(); - worldrenderer.vertex(posMat, xCoord + 16 - 0, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMax, vMin).endVertex(); - worldrenderer.vertex(posMat, xCoord, yCoord + maskTop, 100).color(cols[1], cols[2], cols[3], cols[0]).uv(uMin, vMin).endVertex(); - tessellator.end(); + @Override + public @Nullable FluidStack getFluidStack() { + return this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); } - public static int[] decomposeColor(int color) { - int[] res = new int[4]; - res[0] = color >> 24 & 0xff; - res[1] = color >> 16 & 0xff; - res[2] = color >> 8 & 0xff; - res[3] = color & 0xff; - return res; + @Override + public int getProgress() { + return this.menu.containerData.get(3); } @Override - protected void renderLabels(PoseStack arg, int i, int j) { - arg.pushPose(); - arg.scale(0.75F, 0.75F, 0.75F); - this.font.draw(arg, this.title, (float)this.titleLabelX, (float)this.titleLabelY, 4210752); - arg.popPose(); + public int getProgressRequired() { + return this.menu.containerData.get(4); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/CrookCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/CrookCategory.java index e0d0ed1..8f75f4a 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/CrookCategory.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/CrookCategory.java @@ -46,7 +46,7 @@ public RecipeType getRecipeType() { @Override public Component getTitle() { - return Component.literal("Crooking"); + return Component.translatable("ftbsba.jei.recipe.crook"); } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java new file mode 100644 index 0000000..70396a7 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java @@ -0,0 +1,58 @@ +package dev.ftb.ftbsba.tools.integration.jei; + +import dev.ftb.ftbsba.FTBSBA; +import dev.ftb.ftbsba.tools.recipies.FusingMachineRecipe; +import dev.ftb.ftbsba.tools.recipies.HammerRecipe; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +public class FusingMachineCategory implements IRecipeCategory { + public static final RecipeType TYPE = RecipeType.create(FTBSBA.MOD_ID, "fusing_machine_jei", FusingMachineRecipe.class); + + public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/hammer_jei_background.png"); + + private final IDrawableStatic background; + + public FusingMachineCategory(IGuiHelper guiHelper) { + this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 156, 62).setTextureSize(180, 62).build(); + } + + @Override + public RecipeType getRecipeType() { + return TYPE; + } + + @Override + // TODO: Fixme + public Component getTitle() { + return Component.translatable("ftbsba.jei.recipe.fusing"); + } + + @Override + public IDrawable getBackground() { + return this.background; + } + + @Override + public IDrawable getIcon() { + return null; + } + + @Override + public void setRecipe(IRecipeLayoutBuilder builder, FusingMachineRecipe fusingRecipe, IFocusGroup iFocusGroup) { + for (int i = 0; i < fusingRecipe.ingredients.size(); i++) { + builder.addSlot(RecipeIngredientRole.INPUT, 5 + i * 18, 5).addIngredients(fusingRecipe.ingredients.get(i)); + } + + builder.addSlot(RecipeIngredientRole.OUTPUT, 5, 23).addFluidStack(fusingRecipe.fluidResult.getFluid(), fusingRecipe.fluidResult.getAmount()); + } + +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/HammerCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/HammerCategory.java index 48daec9..936af81 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/HammerCategory.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/HammerCategory.java @@ -32,7 +32,7 @@ public RecipeType getRecipeType() { @Override public Component getTitle() { - return Component.literal("Hammering"); + return Component.translatable("ftbsba.jei.recipe.hammer"); } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java index 67bed69..206c02c 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java @@ -52,6 +52,8 @@ public ResourceLocation getPluginUid() { public void registerCategories(IRecipeCategoryRegistration r) { r.addRecipeCategories(new HammerCategory(r.getJeiHelpers().getGuiHelper())); r.addRecipeCategories(new CrookCategory(r.getJeiHelpers().getGuiHelper())); + r.addRecipeCategories(new FusingMachineCategory(r.getJeiHelpers().getGuiHelper())); + r.addRecipeCategories(new SuperCoolerCategory(r.getJeiHelpers().getGuiHelper())); } @Override @@ -59,32 +61,16 @@ public void registerRecipes(IRecipeRegistration r) { Level level = Minecraft.getInstance().level; r.addRecipes(HammerCategory.TYPE, level.getRecipeManager().getRecipesFor(ToolsRegistry.HAMMER_RECIPE_TYPE.get(), NoInventory.INSTANCE, level)); r.addRecipes(CrookCategory.TYPE, level.getRecipeManager().getRecipesFor(ToolsRegistry.CROOK_RECIPE_TYPE.get(), NoInventory.INSTANCE, level)); - - // CauldronRecipe crap - FluidStack out = new FluidStack(Fluids.WATER, 333); - List leaves = new ArrayList<>(); - List saplings = new ArrayList<>(); - - for (Block block : ForgeRegistries.BLOCKS) { - if (block instanceof LeavesBlock) { - Item item = block.asItem(); - - if (item != Items.AIR) { - leaves.add(item.getDefaultInstance()); - } - } else if (block instanceof SaplingBlock) { - Item item = block.asItem(); - - if (item != Items.AIR) { - saplings.add(item.getDefaultInstance()); - } - } - } + r.addRecipes(FusingMachineCategory.TYPE, level.getRecipeManager().getRecipesFor(ToolsRegistry.FUSING_MACHINE_RECIPE_TYPE.get(), NoInventory.INSTANCE, level)); + r.addRecipes(SuperCoolerCategory.TYPE, level.getRecipeManager().getRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get(), NoInventory.INSTANCE, level)); } @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration r) { HAMMERS.forEach(hammer -> r.addRecipeCatalyst(new ItemStack(hammer.get()), HammerCategory.TYPE)); CROOKS.forEach(crook -> r.addRecipeCatalyst(new ItemStack(crook.get()), CrookCategory.TYPE)); + + r.addRecipeCatalyst(new ItemStack(ToolsRegistry.FUSING_MACHINE_BLOCK_ITEM.get()), FusingMachineCategory.TYPE); + r.addRecipeCatalyst(new ItemStack(ToolsRegistry.SUPER_COOLER_BLOCK_ITEM.get()), SuperCoolerCategory.TYPE); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java new file mode 100644 index 0000000..1ba1295 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java @@ -0,0 +1,55 @@ +package dev.ftb.ftbsba.tools.integration.jei; + +import dev.ftb.ftbsba.FTBSBA; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +public class SuperCoolerCategory implements IRecipeCategory { + public static final RecipeType TYPE = RecipeType.create(FTBSBA.MOD_ID, "super_cooler_jei", SuperCoolerRecipe.class); + + public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/hammer_jei_background.png"); + + private final IDrawableStatic background; + + public SuperCoolerCategory(IGuiHelper guiHelper) { + this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 156, 62).setTextureSize(180, 62).build(); + } + + @Override + public RecipeType getRecipeType() { + return TYPE; + } + + @Override + public Component getTitle() { + return Component.translatable("ftbsba.jei.recipe.super_cooler"); + } + + @Override + public IDrawable getBackground() { + return this.background; + } + + @Override + public IDrawable getIcon() { + return null; + } + + @Override + public void setRecipe(IRecipeLayoutBuilder builder, SuperCoolerRecipe superCoolerRecipe, IFocusGroup iFocusGroup) { + for (int i = 0; i < superCoolerRecipe.ingredients.size(); i++) { + builder.addSlot(RecipeIngredientRole.INPUT, 5 + i * 18, 5).addIngredients(superCoolerRecipe.ingredients.get(i)); + } + + builder.addSlot(RecipeIngredientRole.INPUT, 5, 23).addFluidStack(superCoolerRecipe.fluidIngredient.getFluid(), superCoolerRecipe.fluidIngredient.getAmount()); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java index b444cf6..5e633de 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/kubejs/SuperCoolerRecipeSchema.java @@ -1,8 +1,6 @@ package dev.ftb.ftbsba.tools.integration.kubejs; -import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import dev.latvian.mods.kubejs.fluid.InputFluid; -import dev.latvian.mods.kubejs.fluid.OutputFluid; import dev.latvian.mods.kubejs.item.InputItem; import dev.latvian.mods.kubejs.item.OutputItem; import dev.latvian.mods.kubejs.recipe.RecipeKey; diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java index 45101a7..94199ce 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/FusingMachineRecipeSerializer.java @@ -29,7 +29,7 @@ public FusingMachineRecipe fromJson(ResourceLocation id, JsonObject json) { recipe.fluidResult = FluidStackSerializer.deserialize(fluidResult); recipe.energyComponent = SuperCoolerRecipe.EnergyComponent.fromJson(json.get("energy")); - return null; + return recipe; } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java index fafa148..02bc682 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java @@ -25,10 +25,7 @@ public SuperCoolerRecipe fromJson(ResourceLocation arg, JsonObject jsonObject) { recipe.ingredients.add(Ingredient.fromJson(e)); } - var fluidIngredient = jsonObject.get("fluid").getAsJsonObject(); - recipe.fluidIngredient = FusingMachineRecipeSerializer.FluidStackSerializer.deserialize(fluidIngredient); recipe.energyComponent = SuperCoolerRecipe.EnergyComponent.fromJson(jsonObject.get("energy")); - recipe.result = ShapedRecipe.itemStackFromJson(jsonObject.get("result").getAsJsonObject()); return recipe; @@ -43,12 +40,10 @@ public SuperCoolerRecipe fromJson(ResourceLocation arg, JsonObject jsonObject) { ingredients[i] = Ingredient.fromNetwork(arg2); } - FluidStack fluidIngredient = FluidStack.readFromPacket(arg2); SuperCoolerRecipe.EnergyComponent energyComponent = SuperCoolerRecipe.EnergyComponent.fromNetwork(arg2); var recipe = new SuperCoolerRecipe(arg, groups); recipe.ingredients.addAll(Arrays.asList(ingredients)); - recipe.fluidIngredient = fluidIngredient; recipe.energyComponent = energyComponent; recipe.result = arg2.readItem(); @@ -63,7 +58,6 @@ public void toNetwork(FriendlyByteBuf arg, SuperCoolerRecipe arg2) { i.toNetwork(arg); } - arg2.fluidIngredient.writeToPacket(arg); arg2.energyComponent.toNetwork(arg); arg.writeItem(arg2.result); } From a1df14aa28dfdf3cf7f71048ff6f066e794997ee Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Sun, 11 Feb 2024 17:10:34 +0000 Subject: [PATCH 7/9] feat: added missing lang keys --- .../.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 | 6 +++--- .../.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 | 4 ++-- src/generated/resources/assets/ftbsba/lang/en_us.json | 6 ++++++ .../resources/data/forge/tags/blocks/needs_wood_tool.json | 6 +++--- .../resources/data/ftbsba/tags/blocks/auto_hammers.json | 6 +++--- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 b/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 index 6c21d84..48bb36b 100644 --- a/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 +++ b/src/generated/resources/.cache/75bcd4dba6ca7d365462b0ec45e291d1056349c4 @@ -1,3 +1,3 @@ -// 1.19.2 2024-02-07T15:29:25.340447 Tags for minecraft:block -112b6aaeec7fa81d44ac017f70ffe88b198a7038 data/forge/tags/blocks/needs_wood_tool.json -112b6aaeec7fa81d44ac017f70ffe88b198a7038 data/ftbsba/tags/blocks/auto_hammers.json +// 1.19.2 2024-02-11T17:06:30.745768 Tags for minecraft:block +e4c5cf37f90c4d531461944a5bbc59b8bdf6049b data/forge/tags/blocks/needs_wood_tool.json +e4c5cf37f90c4d531461944a5bbc59b8bdf6049b data/ftbsba/tags/blocks/auto_hammers.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 index afe393a..d044014 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.19.2 2024-02-07T15:29:25.340844 Languages: en_us -41b86f772260d58aaff5a5c0428ce68db1a3d41e assets/ftbsba/lang/en_us.json +// 1.19.2 2024-02-11T17:06:30.747184 Languages: en_us +3abb683509ed20e04d68315667b4e4d159a1601d assets/ftbsba/lang/en_us.json diff --git a/src/generated/resources/assets/ftbsba/lang/en_us.json b/src/generated/resources/assets/ftbsba/lang/en_us.json index 8f793e3..0fc655b 100644 --- a/src/generated/resources/assets/ftbsba/lang/en_us.json +++ b/src/generated/resources/assets/ftbsba/lang/en_us.json @@ -1,8 +1,10 @@ { "block.ftbsba.diamond_auto_hammer": "Diamond Auto-hammer", + "block.ftbsba.fusing_machine": "Fusing Machine", "block.ftbsba.gold_auto_hammer": "Gold Auto-hammer", "block.ftbsba.iron_auto_hammer": "Iron Auto-hammer", "block.ftbsba.netherite_auto_hammer": "Netherite Auto-hammer", + "block.ftbsba.super_cooler": "Super Cooler", "config.jade.plugin_ftbsba.blocks": "FTB Skyblock Addons Blocks", "container.ftbsba.fusing_machine": "Fusing Machine", "container.ftbsba.super_cooler": "Super Cooler", @@ -10,6 +12,10 @@ "ftbsba.jade.input": "Input", "ftbsba.jade.processing": "Processing: %s/%s", "ftbsba.jade.waiting": "Waiting for input: %s ticks", + "ftbsba.jei.recipe.crook": "Crooks", + "ftbsba.jei.recipe.fusing": "Fusing", + "ftbsba.jei.recipe.hammer": "Hammering", + "ftbsba.jei.recipe.super_cooler": "Super Cooler", "ftbsba.tooltip.auto-hammers": "Automatically crushes materials down using the hammer based on the tier of hammer", "ftbsba.tooltip.fireplow": "Hold right click whilst looking at Stone to create lava", "ftbsba.tooltip.fusing_machine": "Used to fuse items together to produce new results", diff --git a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json index b55e555..c2a23d5 100644 --- a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json +++ b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:iron_auto_hammer", - "ftbsba:gold_auto_hammer", "ftbsba:diamond_auto_hammer", - "ftbsba:netherite_auto_hammer" + "ftbsba:iron_auto_hammer", + "ftbsba:netherite_auto_hammer", + "ftbsba:gold_auto_hammer" ] } \ No newline at end of file diff --git a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json index b55e555..c2a23d5 100644 --- a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json +++ b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:iron_auto_hammer", - "ftbsba:gold_auto_hammer", "ftbsba:diamond_auto_hammer", - "ftbsba:netherite_auto_hammer" + "ftbsba:iron_auto_hammer", + "ftbsba:netherite_auto_hammer", + "ftbsba:gold_auto_hammer" ] } \ No newline at end of file From f8c0c4d93f0c383b2e45f8920f72030a0fc8a02e Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Mon, 12 Feb 2024 01:27:43 +0000 Subject: [PATCH 8/9] feat: jei support, code improvements and tidy up --- .../jei/FusingMachineCategory.java | 58 ++++++++++++++++-- .../tools/integration/jei/JEIPlugin.java | 38 +++++++++++- .../integration/jei/SuperCoolerCategory.java | 57 +++++++++++++++-- .../recipies/SuperCoolerRecipeSerializer.java | 3 + .../gui/fusing_machine_background.aseprite | Bin 2030 -> 0 bytes .../textures/gui/jei_fusing_machine.png | Bin 0 -> 491 bytes .../ftbsba/textures/gui/jei_super_cooler.png | Bin 0 -> 592 bytes .../gui/super_cooler_background.aseprite | Bin 2032 -> 0 bytes 8 files changed, 144 insertions(+), 12 deletions(-) delete mode 100644 src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite create mode 100644 src/main/resources/assets/ftbsba/textures/gui/jei_fusing_machine.png create mode 100644 src/main/resources/assets/ftbsba/textures/gui/jei_super_cooler.png delete mode 100644 src/main/resources/assets/ftbsba/textures/gui/super_cooler_background.aseprite diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java index 70396a7..51971ba 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/FusingMachineCategory.java @@ -1,28 +1,46 @@ package dev.ftb.ftbsba.tools.integration.jei; +import com.mojang.blaze3d.vertex.PoseStack; import dev.ftb.ftbsba.FTBSBA; import dev.ftb.ftbsba.tools.recipies.FusingMachineRecipe; import dev.ftb.ftbsba.tools.recipies.HammerRecipe; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; public class FusingMachineCategory implements IRecipeCategory { public static final RecipeType TYPE = RecipeType.create(FTBSBA.MOD_ID, "fusing_machine_jei", FusingMachineRecipe.class); - public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/hammer_jei_background.png"); + public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/jei_fusing_machine.png"); private final IDrawableStatic background; + private final IDrawableAnimated powerBar; + private final IDrawableAnimated progress; public FusingMachineCategory(IGuiHelper guiHelper) { - this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 156, 62).setTextureSize(180, 62).build(); + this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 106, 28) + .setTextureSize(134, 28) + .build(); + + this.powerBar = guiHelper.drawableBuilder(BACKGROUND, 106, 0, 6, 16) + .setTextureSize(134, 28) + .buildAnimated(guiHelper.createTickTimer(120, 16, false), IDrawableAnimated.StartDirection.BOTTOM); + + this.progress = guiHelper.drawableBuilder(BACKGROUND, 112, 0, 22, 16) + .setTextureSize(134, 28) + .buildAnimated(guiHelper.createTickTimer(120, 22, true), IDrawableAnimated.StartDirection.LEFT); } @Override @@ -31,7 +49,6 @@ public RecipeType getRecipeType() { } @Override - // TODO: Fixme public Component getTitle() { return Component.translatable("ftbsba.jei.recipe.fusing"); } @@ -46,13 +63,44 @@ public IDrawable getIcon() { return null; } + @Override + public void draw(FusingMachineRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack stack, double mouseX, double mouseY) { + this.powerBar.draw(stack, 6, 6); + this.progress.draw(stack, 57, 6); + + stack.pushPose(); + stack.translate(5, 25, 0); + stack.scale(0.5F, 0.5F, 0.5F); + + SuperCoolerRecipe.EnergyComponent energyComponent = recipe.energyComponent; + int ticks = energyComponent.ticksToProcess(); + int energyPerTick = energyComponent.fePerTick(); + int totalEnergy = ticks * energyPerTick; + + Gui.drawString(stack, Minecraft.getInstance().font, "%sFE/t (%sFE)".formatted( + energyPerTick, totalEnergy + ), 0, 0, 0xBEFFFFFF); + + stack.popPose(); + + stack.pushPose(); + stack.translate(83, 25, 0); + stack.scale(0.5F, 0.5F, 0.5F); + Gui.drawString(stack, Minecraft.getInstance().font, "%s ticks".formatted(ticks), 0, 0, 0xBEFFFFFF); + + stack.popPose(); + } + @Override public void setRecipe(IRecipeLayoutBuilder builder, FusingMachineRecipe fusingRecipe, IFocusGroup iFocusGroup) { for (int i = 0; i < fusingRecipe.ingredients.size(); i++) { - builder.addSlot(RecipeIngredientRole.INPUT, 5 + i * 18, 5).addIngredients(fusingRecipe.ingredients.get(i)); + builder.addSlot(RecipeIngredientRole.INPUT, 18 + i * 18, 6).addIngredients(fusingRecipe.ingredients.get(i)); } - builder.addSlot(RecipeIngredientRole.OUTPUT, 5, 23).addFluidStack(fusingRecipe.fluidResult.getFluid(), fusingRecipe.fluidResult.getAmount()); + builder.addSlot(RecipeIngredientRole.OUTPUT, 84, 6).addFluidStack(fusingRecipe.fluidResult.getFluid(), fusingRecipe.fluidResult.getAmount()) + .addTooltipCallback((recipeSlotView, tooltip) -> { + tooltip.add(Component.literal(fusingRecipe.fluidResult.getAmount() + " mB")); + }); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java index 206c02c..53ca850 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java @@ -2,12 +2,15 @@ import dev.ftb.ftbsba.FTBSBA; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineContainer; +import dev.ftb.ftbsba.tools.content.fusion.FusingMachineScreen; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerContainer; +import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerScreen; import dev.ftb.ftbsba.tools.recipies.NoInventory; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; -import mezz.jei.api.registration.IRecipeCatalystRegistration; -import mezz.jei.api.registration.IRecipeCategoryRegistration; -import mezz.jei.api.registration.IRecipeRegistration; +import mezz.jei.api.registration.*; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; @@ -73,4 +76,33 @@ public void registerRecipeCatalysts(IRecipeCatalystRegistration r) { r.addRecipeCatalyst(new ItemStack(ToolsRegistry.FUSING_MACHINE_BLOCK_ITEM.get()), FusingMachineCategory.TYPE); r.addRecipeCatalyst(new ItemStack(ToolsRegistry.SUPER_COOLER_BLOCK_ITEM.get()), SuperCoolerCategory.TYPE); } + + @Override + public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { + registration.addRecipeTransferHandler( + SuperCoolerContainer.class, + ToolsRegistry.SUPER_COOLER_CONTAINER.get(), + SuperCoolerCategory.TYPE, + 36, + 3, + 0, + 36 + ); + + registration.addRecipeTransferHandler( + FusingMachineContainer.class, + ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), + FusingMachineCategory.TYPE, + 36, + 2, + 0, + 36 + ); + } + + @Override + public void registerGuiHandlers(IGuiHandlerRegistration registration) { + registration.addRecipeClickArea(SuperCoolerScreen.class, 80, 28, 22, 16, SuperCoolerCategory.TYPE); + registration.addRecipeClickArea(FusingMachineScreen.class, 91, 28, 22, 16, FusingMachineCategory.TYPE); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java index 1ba1295..e6b72fe 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/SuperCoolerCategory.java @@ -1,27 +1,41 @@ package dev.ftb.ftbsba.tools.integration.jei; +import com.mojang.blaze3d.vertex.PoseStack; import dev.ftb.ftbsba.FTBSBA; import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.drawable.IDrawableAnimated; import mezz.jei.api.gui.drawable.IDrawableStatic; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.category.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; public class SuperCoolerCategory implements IRecipeCategory { public static final RecipeType TYPE = RecipeType.create(FTBSBA.MOD_ID, "super_cooler_jei", SuperCoolerRecipe.class); - public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/hammer_jei_background.png"); + public static final ResourceLocation BACKGROUND = new ResourceLocation(FTBSBA.MOD_ID, "textures/gui/jei_super_cooler.png"); private final IDrawableStatic background; + private final IDrawableAnimated powerBar; + private final IDrawableAnimated progress; public SuperCoolerCategory(IGuiHelper guiHelper) { - this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 156, 62).setTextureSize(180, 62).build(); + this.background = guiHelper.drawableBuilder(BACKGROUND, 0, 0, 146, 28).setTextureSize(174, 28).build(); + this.powerBar = guiHelper.drawableBuilder(BACKGROUND, 146, 0, 6, 16) + .setTextureSize(174, 28) + .buildAnimated(guiHelper.createTickTimer(120, 16, false), IDrawableAnimated.StartDirection.BOTTOM); + + this.progress = guiHelper.drawableBuilder(BACKGROUND, 152, 0, 22, 16) + .setTextureSize(174, 28) + .buildAnimated(guiHelper.createTickTimer(120, 22, true), IDrawableAnimated.StartDirection.LEFT); } @Override @@ -44,12 +58,47 @@ public IDrawable getIcon() { return null; } + @Override + public void draw(SuperCoolerRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack stack, double mouseX, double mouseY) { + IRecipeCategory.super.draw(recipe, recipeSlotsView, stack, mouseX, mouseY); + this.powerBar.draw(stack, 6, 6); + this.progress.draw(stack, 97, 6); + + stack.pushPose(); + stack.translate(5, 25, 0); + stack.scale(0.5F, 0.5F, 0.5F); + + SuperCoolerRecipe.EnergyComponent energyComponent = recipe.energyComponent; + int ticks = energyComponent.ticksToProcess(); + int energyPerTick = energyComponent.fePerTick(); + int totalEnergy = ticks * energyPerTick; + + Gui.drawString(stack, Minecraft.getInstance().font, "%sFE/t (%sFE)".formatted( + energyPerTick, totalEnergy + ), 0, 0, 0xBEFFFFFF); + + stack.popPose(); + + stack.pushPose(); + stack.translate(96, 25, 0); + stack.scale(0.5F, 0.5F, 0.5F); + Gui.drawString(stack, Minecraft.getInstance().font, "%s ticks".formatted(ticks), 0, 0, 0xBEFFFFFF); + + stack.popPose(); + } + @Override public void setRecipe(IRecipeLayoutBuilder builder, SuperCoolerRecipe superCoolerRecipe, IFocusGroup iFocusGroup) { for (int i = 0; i < superCoolerRecipe.ingredients.size(); i++) { - builder.addSlot(RecipeIngredientRole.INPUT, 5 + i * 18, 5).addIngredients(superCoolerRecipe.ingredients.get(i)); + builder.addSlot(RecipeIngredientRole.INPUT, 40 + i * 18, 6).addIngredients(superCoolerRecipe.ingredients.get(i)); } - builder.addSlot(RecipeIngredientRole.INPUT, 5, 23).addFluidStack(superCoolerRecipe.fluidIngredient.getFluid(), superCoolerRecipe.fluidIngredient.getAmount()); + builder.addSlot(RecipeIngredientRole.OUTPUT, 124, 6).addItemStack(superCoolerRecipe.result); + + builder.addSlot(RecipeIngredientRole.CATALYST, 18, 6) + .addFluidStack(superCoolerRecipe.fluidIngredient.getFluid(), superCoolerRecipe.fluidIngredient.getAmount()) + .addTooltipCallback((recipeSlotView, tooltip) -> { + tooltip.add(Component.literal(superCoolerRecipe.fluidIngredient.getAmount() + " mB")); + }); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java index 02bc682..c06caa5 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipeSerializer.java @@ -27,6 +27,7 @@ public SuperCoolerRecipe fromJson(ResourceLocation arg, JsonObject jsonObject) { recipe.energyComponent = SuperCoolerRecipe.EnergyComponent.fromJson(jsonObject.get("energy")); recipe.result = ShapedRecipe.itemStackFromJson(jsonObject.get("result").getAsJsonObject()); + recipe.fluidIngredient = FusingMachineRecipeSerializer.FluidStackSerializer.deserialize(jsonObject.get("fluid").getAsJsonObject()); return recipe; } @@ -46,6 +47,7 @@ public SuperCoolerRecipe fromJson(ResourceLocation arg, JsonObject jsonObject) { recipe.ingredients.addAll(Arrays.asList(ingredients)); recipe.energyComponent = energyComponent; recipe.result = arg2.readItem(); + recipe.fluidIngredient = arg2.readFluidStack(); return recipe; } @@ -60,5 +62,6 @@ public void toNetwork(FriendlyByteBuf arg, SuperCoolerRecipe arg2) { arg2.energyComponent.toNetwork(arg); arg.writeItem(arg2.result); + arg.writeFluidStack(arg2.fluidIngredient); } } diff --git a/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite b/src/main/resources/assets/ftbsba/textures/gui/fusing_machine_background.aseprite deleted file mode 100644 index cdb4266acd605f186a156ba56dea8b02242f58c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2030 zcmeHIdrVt(6#lhP80uD#msDnp47wPX4sjNbH~VX$RYagZ%k=3GLglaj#zr>xEqCflIM!^=|3V;5{My}dtA+aVCK@gEca@VmX= zJ^jx4<(%|8xt;JuXy_aVAr9iK0757O?ghvZ$0;Izxc&`fL;tyHzN;%A8ic^@D{{45 z)NTfZFp>PBlCmf>A7TJPot>S)B_$=m>FMdfQmGUe06aT8>yF{8$z+1KEHd)Xth>fD zV?VzQa8@jaQ^S>&9SD7+R6>kHLiWH(gf6%kl<4Sa;K|@%&Ab9nQ2ytC`U_a0(A&9@ zPTRp<@D_{(SHV(Hz)WDU5j=$8uK=&WC~(PXQHXP|0ALGv;*S5Dyc)*x7I`fi&bc)_ zl)U?>GEcZ{($}37#duCX=Q$ngIsLrn^oAZTOeu1YjUj#rc&+4XEceXW>h-8-dtMD` zC5EFeuMWCcRa6}FlJ>H2SJv>Z@TdD8-@A5a=~snSf&wNiYoFw;S3(Q$@Szif!bCMW zqWCf*+UEFi+`oyIw^2evwME7MRu&WV;b&d@N(rHImiVcqSIu6Trb2JbNio9|N0?0v zU(M+3I;;UT``Vn*8kVY+L% z8`BLbn`7Ayzx^2wv3&DJ%5aQ3IHP!bTAq|99%`fvil8nkk92*gj6W z(ZXi39o;)7i8SKi7v*Nzi?0>q7wq>t=(C~t{5F*l=XDwtaTsT^G#!{Qfqx}_9?coZ zage22LvEjeCQ12YJ6tMB;tLy3;?_RX*i_flrlPCy%=wWO15F9xw4U_q&VA%+L)CX% zWM@jc0$K-&*mq7b@7;AI<#SSRN1YleEa$5uRk-<5<8i?!Ti&GPg%7AkTp*zI$!1wb zVc9MABbkF_(#g-GS)1ea!?@+uU+&}4=Gtv5rET<>Aup;5v)05q2^z4HI8oKZ-kfQ| z;f;4Nu~*l+hX_w;t5y#+<1>ovXZ4xGWsY~X786IsNSNHr{`fSa-bT|jzkZCIhv^o+ zE|FFbd`&UJ-wqg$m6^3mL8$S5dEq8pGjYg4EkzC`v>Y%tXmM|VOopFg>*6i7ll}d~ zMSZPZwgiL<-#q(!0jm#^5$&vf6`ODcGqVru{3({YefPM+{OG4qTPxOh{2b|KIgvzN z&^p*&9{dZ{BQLbD%)TfAjXiG)?qfs+!UB%qxi$jIH_EiX7TK~)% ziL1_Q*}BTph_ltt$N!0QAH?x^sP5j%>ta{AH@XII!G#%k=w+CpvO>TM@Px$rAb6VRA_^*6=i*L4fRn@AFxke*YRr5fV>pt%VTQXJ12tlI{68oy>oXV{lBD928?G z{M_$J;@ae(7&{?F#h5V3K{0khs){i&m%}JVRaM4D2LPm$Xqra&uJ=VsiD4MlhB2OR zD`MrrbpDhTW8zT`V*;zH(o#y}!*yL_UUppTeW~jjm&*k);<&o)B`Brz63Jra!E}Dx zRPuSdt=i9o5JK=OdBRdTQemwa3D8<=is8Y3ki*tvyd~JHZCf^qyRXsE+&^8si%@hDS$%6P)e;HBj@q9mLuhN zjJXs*A!4LpYdKO?43iW9#R%pI6~iV4P>2|zFVS`d9ihi?NdXihMoe-|CGUaLhYgn$ z0PqrXv!j#yBiEKt3{Ogu0-zXPlqLm0F`iPQ6ad9=QmPbIlv3Ko()GT?ijyN}G4qh? h{Dcrf2qA=I;THjFqn$p+RRsV5002ovPDHLkV1i6G*Yf}X literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/gui/jei_super_cooler.png b/src/main/resources/assets/ftbsba/textures/gui/jei_super_cooler.png new file mode 100644 index 0000000000000000000000000000000000000000..db8d4d8b3f844239d159d560dd145ce9347b5a55 GIT binary patch literal 592 zcmV-W0Px%3Q0skRCt{2nlWy|FcgM=SDjJ2(;1bajFC8pFTfoLIYZ*BWawE~5OZ^n*C`bW zb{dRbr{@30VE)+X%j3m~0wDo7zQ2p@_{Zs_eDXv@lv2*`KKq0cGURQwvVU+od1sEv zOL0jMzRu?;xh{DrE(t=6irZt8*D7vN6xM*{a*4%af%STgvMfi(-a^dWp04X=kuzLp zF2t(1Jwth271!EmcU=dqHMZOBuyk9;PbGG4+qU<_1kbUo^G_&>;;!El0JPR9%kpae zF)MD*rM%8oL2GS2zTfY0wp?AV@l%PJ+qUhja%}7L!5AYpiN**qf7`!>tKy2t-51L+ zPbsCmdfb)k>bjFyxpO1rI(_7gfwSU9KtzN$XBjXDd0iFvCBnI?s^YFfE~J*%RdK7T z^2)30+L_lhjbE!k=1EF)-IlNO-3$vGa6QF3#rxGre{ikqCxW&;3TlDS%p z9D3X_X#t9xoWtROrfGuZrP@_^_1ryhF(xelJcT?Nxt$!OO##Ktgh!GVptxD^Xwm`{ z_uun~(gFd*y?n_!B(ZXH;!&k_VvLbr_!+y~?WT;MN|fBWCknQ3qWisJTM|6yjPRdqE#dd28ZEf%CX}b*;vGI?IKYVWQ zb5Eah-kg&@C%3k6gl@KQ5aJ+C1Q0?+a4$lIIDQd{;QBYP5BhuV#00v=K!Z5A!&3q+ zm$Y+$kdUIfr{pfl+z$x=A%npHTvJm6oR^meER)HA0l-eDGZ@2HqtOU)U0T|MY_KLY z6QM8z&ZeisscEfNk5G4UF~lS;ZU>x1=uCh?kw_%K*4Ws_`wBck`JeykFR%cGeE&xJ zZ3lP3TQC+}1xrBzGl9WI@DPH(0=xpFz$L#$asIsmfGyxjF#d1y<1iLKg|}ol|JDf5 zONEDv%afN)h6j@=8$+j`37wXPPCpwuoxyNn%9P;P1mb&u*UF*Bxru_>;~P-+_PeJo zzV`D%?P~tn=lk?k%ts#1D{G?-sh>&pl4DOBu4lavrC=SIul@Yai?drTx~$r(9%Y&I zja%-9(szZL&7+(3rL5TI9c(Y|H7YHt$br4Tb|jdLIr%E zy2IR(JFU6d8LVD-y2zKV%2wE^O70eix^6nT_Ec_Pz8U{W?dOj4u%$Y(Q1AW3t4(vd zT5~|iVfB~utyqamKCib>o61FGkK@{VCWVx=yeLvA|vso3HA5hI^(zdCZTpTsd*amG`RhJarHdDm#cDK3w|jWDmu|L z^qnb!veL7e73?=oR_>f`YM<{pCRX~CZ<@OB+AE3jt;$#Tu!Sm3vlBOZypn64n6W8S zXQfX?HsT+;lXTN{SABlv5GH?oIu&1a+v%q3aS<-_G~nnb zZVt!ELN^OJly^P0-Xf}bG$Un$j)veZOG;Gsu_XBh}822s1 zxr)qY(xjM6u~I=8#dO!X_i!f<#A*aPeZ#hiQIuG^_+7`hslsVW95GUu(o z?KQK^L(m!NuGS09BzJ&OcaV#3;dm>hQ)@`{6y8EdxpFEwovXIhhyENKqt-N>l}`h=uo40#R_q(nDh4b64%RUZ01SFQ-Nac^2PDVg8pcP&TUw;YJH%N zw``sEDB^4rhKU|+IU*Mb(8-CYq4YpG9}U2JaB&6!dJbmL)+Y)c;h``?Dla&y;BU&f T+%VD6#NrRHaM72AqW(VtFWzTZ From 3b5dc75f3837761fab193e44ab5cb6fffb0f091e Mon Sep 17 00:00:00 2001 From: Des Herriott Date: Tue, 13 Feb 2024 16:45:07 +0000 Subject: [PATCH 9/9] chore: lots of dev work for fusing machine and super cooler --- .gitignore | 3 + .../c622617f6fabf890a00b9275cd5f643584a8a2c8 | 4 +- .../blockstates/diamond_auto_hammer.json | 24 +- .../ftbsba/blockstates/fusing_machine.json | 34 ++ .../ftbsba/blockstates/gold_auto_hammer.json | 24 +- .../ftbsba/blockstates/iron_auto_hammer.json | 24 +- .../blockstates/netherite_auto_hammer.json | 24 +- .../ftbsba/blockstates/super_cooler.json | 34 ++ .../resources/assets/ftbsba/lang/en_us.json | 2 + .../ftbsba/models/block/fusing_machine.json | 8 + .../models/block/fusing_machine_active.json | 8 + .../ftbsba/models/block/super_cooler.json | 8 + .../models/block/super_cooler_active.json | 8 + .../ftbsba/models/item/fusing_machine.json | 3 + .../ftbsba/models/item/super_cooler.json | 3 + .../forge/tags/blocks/needs_wood_tool.json | 6 +- .../loot_tables/blocks/fusing_machine.json | 42 +++ .../loot_tables/blocks/super_cooler.json | 42 +++ .../data/ftbsba/tags/blocks/auto_hammers.json | 6 +- src/main/java/dev/ftb/ftbsba/FTBSBA.java | 12 + .../dev/ftb/ftbsba/tools/ToolsClient.java | 19 ++ .../java/dev/ftb/ftbsba/tools/ToolsData.java | 90 ++++- .../dev/ftb/ftbsba/tools/ToolsRegistry.java | 3 + .../content/autohammer/AutoHammerBlock.java | 9 +- .../autohammer/AutoHammerBlockEntity.java | 8 +- .../content/core/AbstractMachineBlock.java | 159 +++++++++ .../core/AbstractMachineBlockEntity.java | 52 +++ .../content/core/AbstractMachineMenu.java | 139 ++++++++ .../tools/content/core/EmittingFluidTank.java | 30 ++ .../content/core/FluidAndEnergyScreen.java | 15 +- .../FluidEnergyProcessorContainerData.java | 49 +-- .../content/core/FluidEnergyProvider.java | 9 +- .../tools/content/core/IOStackHandler.java | 2 +- .../tools/content/core/RecipeCaches.java | 96 ++++++ .../content/fusion/FusingMachineBlock.java | 51 +-- .../fusion/FusingMachineBlockEntity.java | 282 +++++++--------- .../fusion/FusingMachineContainer.java | 101 +----- .../content/fusion/FusingMachineScreen.java | 20 +- .../content/supercooler/SuperCoolerBlock.java | 52 +-- .../supercooler/SuperCoolerBlockEntity.java | 314 +++++++----------- .../supercooler/SuperCoolerContainer.java | 86 +---- .../supercooler/SuperCoolerScreen.java | 20 +- .../tools/integration/jei/JEIPlugin.java | 29 +- .../ftb/ftbsba/tools/net/FluidTankSync.java | 38 +++ .../ftb/ftbsba/tools/net/NetworkHandler.java | 39 +++ .../tools/recipies/SuperCoolerRecipe.java | 4 +- .../textures/block/fusing_machine_front.png | Bin 0 -> 3451 bytes .../block/fusing_machine_front_active.png | Bin 0 -> 3428 bytes .../textures/block/fusing_machine_top.png | Bin 0 -> 3367 bytes .../block/fusing_machine_top_active.png | Bin 0 -> 3378 bytes .../textures/block/generic_machine_side.png | Bin 0 -> 3308 bytes .../textures/block/super_cooler_front.png | Bin 0 -> 3453 bytes .../block/super_cooler_front_active.png | Bin 0 -> 3409 bytes .../textures/block/super_cooler_top.png | Bin 0 -> 3364 bytes .../block/super_cooler_top_active.png | Bin 0 -> 3382 bytes 55 files changed, 1243 insertions(+), 792 deletions(-) create mode 100644 src/generated/resources/assets/ftbsba/blockstates/fusing_machine.json create mode 100644 src/generated/resources/assets/ftbsba/blockstates/super_cooler.json create mode 100644 src/generated/resources/assets/ftbsba/models/block/fusing_machine.json create mode 100644 src/generated/resources/assets/ftbsba/models/block/fusing_machine_active.json create mode 100644 src/generated/resources/assets/ftbsba/models/block/super_cooler.json create mode 100644 src/generated/resources/assets/ftbsba/models/block/super_cooler_active.json create mode 100644 src/generated/resources/assets/ftbsba/models/item/fusing_machine.json create mode 100644 src/generated/resources/assets/ftbsba/models/item/super_cooler.json create mode 100644 src/generated/resources/data/ftbsba/loot_tables/blocks/fusing_machine.json create mode 100644 src/generated/resources/data/ftbsba/loot_tables/blocks/super_cooler.json create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlock.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlockEntity.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineMenu.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/content/core/RecipeCaches.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/net/FluidTankSync.java create mode 100644 src/main/java/dev/ftb/ftbsba/tools/net/NetworkHandler.java create mode 100644 src/main/resources/assets/ftbsba/textures/block/fusing_machine_front.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/fusing_machine_front_active.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/fusing_machine_top.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/fusing_machine_top_active.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/generic_machine_side.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/super_cooler_front.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/super_cooler_front_active.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/super_cooler_top.png create mode 100644 src/main/resources/assets/ftbsba/textures/block/super_cooler_top_active.png diff --git a/.gitignore b/.gitignore index bcad8f8..ded8269 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ bin/ # fabric run/ + +# datagen caches +**/.cache \ No newline at end of file diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 index d044014..ef50810 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.19.2 2024-02-11T17:06:30.747184 Languages: en_us -3abb683509ed20e04d68315667b4e4d159a1601d assets/ftbsba/lang/en_us.json +// 1.19.2 2024-02-13T15:18:07.800475465 Languages: en_us +ec5bc7afeca422d8fd3cce464432d445749ccae4 assets/ftbsba/lang/en_us.json diff --git a/src/generated/resources/assets/ftbsba/blockstates/diamond_auto_hammer.json b/src/generated/resources/assets/ftbsba/blockstates/diamond_auto_hammer.json index aeaa9dd..837a969 100644 --- a/src/generated/resources/assets/ftbsba/blockstates/diamond_auto_hammer.json +++ b/src/generated/resources/assets/ftbsba/blockstates/diamond_auto_hammer.json @@ -21,61 +21,61 @@ { "apply": { "model": "ftbsba:block/diamond_auto_hammer", - "y": 180 + "y": 90 }, "when": { "active": "false", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/diamond_auto_hammer_active", - "y": 180 + "y": 90 }, "when": { "active": "true", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/diamond_auto_hammer", - "y": 270 + "y": 180 }, "when": { "active": "false", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/diamond_auto_hammer_active", - "y": 270 + "y": 180 }, "when": { "active": "true", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/diamond_auto_hammer", - "y": 90 + "y": 270 }, "when": { "active": "false", - "facing": "east" + "facing": "west" } }, { "apply": { "model": "ftbsba:block/diamond_auto_hammer_active", - "y": 90 + "y": 270 }, "when": { "active": "true", - "facing": "east" + "facing": "west" } } ] diff --git a/src/generated/resources/assets/ftbsba/blockstates/fusing_machine.json b/src/generated/resources/assets/ftbsba/blockstates/fusing_machine.json new file mode 100644 index 0000000..9fb4d5f --- /dev/null +++ b/src/generated/resources/assets/ftbsba/blockstates/fusing_machine.json @@ -0,0 +1,34 @@ +{ + "variants": { + "active=false,facing=east": { + "model": "ftbsba:block/fusing_machine", + "y": 90 + }, + "active=false,facing=north": { + "model": "ftbsba:block/fusing_machine" + }, + "active=false,facing=south": { + "model": "ftbsba:block/fusing_machine", + "y": 180 + }, + "active=false,facing=west": { + "model": "ftbsba:block/fusing_machine", + "y": 270 + }, + "active=true,facing=east": { + "model": "ftbsba:block/fusing_machine_active", + "y": 90 + }, + "active=true,facing=north": { + "model": "ftbsba:block/fusing_machine_active" + }, + "active=true,facing=south": { + "model": "ftbsba:block/fusing_machine_active", + "y": 180 + }, + "active=true,facing=west": { + "model": "ftbsba:block/fusing_machine_active", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/blockstates/gold_auto_hammer.json b/src/generated/resources/assets/ftbsba/blockstates/gold_auto_hammer.json index 89a2f6d..9a19c27 100644 --- a/src/generated/resources/assets/ftbsba/blockstates/gold_auto_hammer.json +++ b/src/generated/resources/assets/ftbsba/blockstates/gold_auto_hammer.json @@ -21,61 +21,61 @@ { "apply": { "model": "ftbsba:block/gold_auto_hammer", - "y": 180 + "y": 90 }, "when": { "active": "false", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/gold_auto_hammer_active", - "y": 180 + "y": 90 }, "when": { "active": "true", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/gold_auto_hammer", - "y": 270 + "y": 180 }, "when": { "active": "false", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/gold_auto_hammer_active", - "y": 270 + "y": 180 }, "when": { "active": "true", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/gold_auto_hammer", - "y": 90 + "y": 270 }, "when": { "active": "false", - "facing": "east" + "facing": "west" } }, { "apply": { "model": "ftbsba:block/gold_auto_hammer_active", - "y": 90 + "y": 270 }, "when": { "active": "true", - "facing": "east" + "facing": "west" } } ] diff --git a/src/generated/resources/assets/ftbsba/blockstates/iron_auto_hammer.json b/src/generated/resources/assets/ftbsba/blockstates/iron_auto_hammer.json index 975f8de..12a5c4c 100644 --- a/src/generated/resources/assets/ftbsba/blockstates/iron_auto_hammer.json +++ b/src/generated/resources/assets/ftbsba/blockstates/iron_auto_hammer.json @@ -21,61 +21,61 @@ { "apply": { "model": "ftbsba:block/iron_auto_hammer", - "y": 180 + "y": 90 }, "when": { "active": "false", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/iron_auto_hammer_active", - "y": 180 + "y": 90 }, "when": { "active": "true", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/iron_auto_hammer", - "y": 270 + "y": 180 }, "when": { "active": "false", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/iron_auto_hammer_active", - "y": 270 + "y": 180 }, "when": { "active": "true", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/iron_auto_hammer", - "y": 90 + "y": 270 }, "when": { "active": "false", - "facing": "east" + "facing": "west" } }, { "apply": { "model": "ftbsba:block/iron_auto_hammer_active", - "y": 90 + "y": 270 }, "when": { "active": "true", - "facing": "east" + "facing": "west" } } ] diff --git a/src/generated/resources/assets/ftbsba/blockstates/netherite_auto_hammer.json b/src/generated/resources/assets/ftbsba/blockstates/netherite_auto_hammer.json index 3c3b0f7..5b218d8 100644 --- a/src/generated/resources/assets/ftbsba/blockstates/netherite_auto_hammer.json +++ b/src/generated/resources/assets/ftbsba/blockstates/netherite_auto_hammer.json @@ -21,61 +21,61 @@ { "apply": { "model": "ftbsba:block/netherite_auto_hammer", - "y": 180 + "y": 90 }, "when": { "active": "false", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/netherite_auto_hammer_active", - "y": 180 + "y": 90 }, "when": { "active": "true", - "facing": "south" + "facing": "east" } }, { "apply": { "model": "ftbsba:block/netherite_auto_hammer", - "y": 270 + "y": 180 }, "when": { "active": "false", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/netherite_auto_hammer_active", - "y": 270 + "y": 180 }, "when": { "active": "true", - "facing": "west" + "facing": "south" } }, { "apply": { "model": "ftbsba:block/netherite_auto_hammer", - "y": 90 + "y": 270 }, "when": { "active": "false", - "facing": "east" + "facing": "west" } }, { "apply": { "model": "ftbsba:block/netherite_auto_hammer_active", - "y": 90 + "y": 270 }, "when": { "active": "true", - "facing": "east" + "facing": "west" } } ] diff --git a/src/generated/resources/assets/ftbsba/blockstates/super_cooler.json b/src/generated/resources/assets/ftbsba/blockstates/super_cooler.json new file mode 100644 index 0000000..ac37fcf --- /dev/null +++ b/src/generated/resources/assets/ftbsba/blockstates/super_cooler.json @@ -0,0 +1,34 @@ +{ + "variants": { + "active=false,facing=east": { + "model": "ftbsba:block/super_cooler", + "y": 90 + }, + "active=false,facing=north": { + "model": "ftbsba:block/super_cooler" + }, + "active=false,facing=south": { + "model": "ftbsba:block/super_cooler", + "y": 180 + }, + "active=false,facing=west": { + "model": "ftbsba:block/super_cooler", + "y": 270 + }, + "active=true,facing=east": { + "model": "ftbsba:block/super_cooler_active", + "y": 90 + }, + "active=true,facing=north": { + "model": "ftbsba:block/super_cooler_active" + }, + "active=true,facing=south": { + "model": "ftbsba:block/super_cooler_active", + "y": 180 + }, + "active=true,facing=west": { + "model": "ftbsba:block/super_cooler_active", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/lang/en_us.json b/src/generated/resources/assets/ftbsba/lang/en_us.json index 0fc655b..fba8092 100644 --- a/src/generated/resources/assets/ftbsba/lang/en_us.json +++ b/src/generated/resources/assets/ftbsba/lang/en_us.json @@ -17,7 +17,9 @@ "ftbsba.jei.recipe.hammer": "Hammering", "ftbsba.jei.recipe.super_cooler": "Super Cooler", "ftbsba.tooltip.auto-hammers": "Automatically crushes materials down using the hammer based on the tier of hammer", + "ftbsba.tooltip.energy": "Energy: %s FE", "ftbsba.tooltip.fireplow": "Hold right click whilst looking at Stone to create lava", + "ftbsba.tooltip.fluid": "Fluid: %smB %s", "ftbsba.tooltip.fusing_machine": "Used to fuse items together to produce new results", "ftbsba.tooltip.hammers": "Crushes materials down to their core components", "ftbsba.tooltip.super_cooler": "Used to super-cool items to produce new results", diff --git a/src/generated/resources/assets/ftbsba/models/block/fusing_machine.json b/src/generated/resources/assets/ftbsba/models/block/fusing_machine.json new file mode 100644 index 0000000..79382bd --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/block/fusing_machine.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "front": "ftbsba:block/fusing_machine_front", + "side": "ftbsba:block/generic_machine_side", + "top": "ftbsba:block/fusing_machine_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/models/block/fusing_machine_active.json b/src/generated/resources/assets/ftbsba/models/block/fusing_machine_active.json new file mode 100644 index 0000000..2df149a --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/block/fusing_machine_active.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "front": "ftbsba:block/fusing_machine_front_active", + "side": "ftbsba:block/generic_machine_side", + "top": "ftbsba:block/fusing_machine_top_active" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/models/block/super_cooler.json b/src/generated/resources/assets/ftbsba/models/block/super_cooler.json new file mode 100644 index 0000000..bb232e1 --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/block/super_cooler.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "front": "ftbsba:block/super_cooler_front", + "side": "ftbsba:block/generic_machine_side", + "top": "ftbsba:block/super_cooler_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/models/block/super_cooler_active.json b/src/generated/resources/assets/ftbsba/models/block/super_cooler_active.json new file mode 100644 index 0000000..91c7471 --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/block/super_cooler_active.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "front": "ftbsba:block/super_cooler_front_active", + "side": "ftbsba:block/generic_machine_side", + "top": "ftbsba:block/super_cooler_top_active" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/models/item/fusing_machine.json b/src/generated/resources/assets/ftbsba/models/item/fusing_machine.json new file mode 100644 index 0000000..f1914fb --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/item/fusing_machine.json @@ -0,0 +1,3 @@ +{ + "parent": "ftbsba:block/fusing_machine" +} \ No newline at end of file diff --git a/src/generated/resources/assets/ftbsba/models/item/super_cooler.json b/src/generated/resources/assets/ftbsba/models/item/super_cooler.json new file mode 100644 index 0000000..2d188aa --- /dev/null +++ b/src/generated/resources/assets/ftbsba/models/item/super_cooler.json @@ -0,0 +1,3 @@ +{ + "parent": "ftbsba:block/super_cooler" +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json index c2a23d5..60a808a 100644 --- a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json +++ b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:diamond_auto_hammer", "ftbsba:iron_auto_hammer", - "ftbsba:netherite_auto_hammer", - "ftbsba:gold_auto_hammer" + "ftbsba:diamond_auto_hammer", + "ftbsba:gold_auto_hammer", + "ftbsba:netherite_auto_hammer" ] } \ No newline at end of file diff --git a/src/generated/resources/data/ftbsba/loot_tables/blocks/fusing_machine.json b/src/generated/resources/data/ftbsba/loot_tables/blocks/fusing_machine.json new file mode 100644 index 0000000..d4588d4 --- /dev/null +++ b/src/generated/resources/data/ftbsba/loot_tables/blocks/fusing_machine.json @@ -0,0 +1,42 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "ops": [ + { + "op": "replace", + "source": "energy", + "target": "BlockEntityTag.energy" + }, + { + "op": "replace", + "source": "fluid", + "target": "BlockEntityTag.fluid" + } + ], + "source": "block_entity" + } + ], + "name": "ftbsba:fusing_machine" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/ftbsba/loot_tables/blocks/super_cooler.json b/src/generated/resources/data/ftbsba/loot_tables/blocks/super_cooler.json new file mode 100644 index 0000000..06ac5ed --- /dev/null +++ b/src/generated/resources/data/ftbsba/loot_tables/blocks/super_cooler.json @@ -0,0 +1,42 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "ops": [ + { + "op": "replace", + "source": "energy", + "target": "BlockEntityTag.energy" + }, + { + "op": "replace", + "source": "fluid", + "target": "BlockEntityTag.fluid" + } + ], + "source": "block_entity" + } + ], + "name": "ftbsba:super_cooler" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json index c2a23d5..60a808a 100644 --- a/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json +++ b/src/generated/resources/data/ftbsba/tags/blocks/auto_hammers.json @@ -1,8 +1,8 @@ { "values": [ - "ftbsba:diamond_auto_hammer", "ftbsba:iron_auto_hammer", - "ftbsba:netherite_auto_hammer", - "ftbsba:gold_auto_hammer" + "ftbsba:diamond_auto_hammer", + "ftbsba:gold_auto_hammer", + "ftbsba:netherite_auto_hammer" ] } \ No newline at end of file diff --git a/src/main/java/dev/ftb/ftbsba/FTBSBA.java b/src/main/java/dev/ftb/ftbsba/FTBSBA.java index e2490fe..01b32ce 100644 --- a/src/main/java/dev/ftb/ftbsba/FTBSBA.java +++ b/src/main/java/dev/ftb/ftbsba/FTBSBA.java @@ -4,7 +4,10 @@ import dev.ftb.ftbsba.tools.ToolsClient; import dev.ftb.ftbsba.tools.ToolsMain; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.core.RecipeCaches; +import dev.ftb.ftbsba.tools.net.NetworkHandler; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.AddReloadListenerEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; @@ -23,6 +26,7 @@ public class FTBSBA { public FTBSBA() { ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, FTBSAConfig.COMMON_CONFIG); + IEventBus forgeBus = MinecraftForge.EVENT_BUS; IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); // Register everything that's part of the tools system @@ -31,6 +35,10 @@ public FTBSBA() { modBus.addListener(this::clientSetup); modBus.addListener(this::postSetup); + forgeBus.addListener(this::addReloadListeners); + + NetworkHandler.init(); + MinecraftForge.EVENT_BUS.register(this); } @@ -41,4 +49,8 @@ private void clientSetup(final FMLClientSetupEvent event) { public void postSetup(FMLLoadCompleteEvent event) { ToolsMain.setup(); } + + private void addReloadListeners(AddReloadListenerEvent event) { + event.addListener(new RecipeCaches.ReloadListener()); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java index 78faa21..6e80178 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsClient.java @@ -2,9 +2,16 @@ import dev.ftb.ftbsba.tools.content.fusion.FusingMachineScreen; import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerScreen; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +import java.util.Optional; public class ToolsClient { public static void init() { @@ -16,4 +23,16 @@ public static void init() { MenuScreens.register(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), FusingMachineScreen::new); MenuScreens.register(ToolsRegistry.SUPER_COOLER_CONTAINER.get(), SuperCoolerScreen::new); } + + public static Optional getBlockEntityAt(BlockPos pos, Class cls) { + Level level = Minecraft.getInstance().level; + if (level != null && pos != null) { + BlockEntity te = level.getBlockEntity(pos); + if (te != null && cls.isAssignableFrom(te.getClass())) { + //noinspection unchecked + return Optional.of((T) te); + } + } + return Optional.empty(); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java index 4990e93..6188ee2 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsData.java @@ -3,16 +3,16 @@ import com.google.common.collect.Lists; import com.mojang.datafixers.util.Pair; import dev.ftb.ftbsba.FTBSBA; -import dev.ftb.ftbsba.tools.content.autohammer.AutoHammerBlock; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlock; import dev.ftb.ftbsba.tools.loot.CrookModifier; import dev.ftb.ftbsba.tools.loot.HammerModifier; +import net.minecraft.Util; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.core.Direction; import net.minecraft.data.DataGenerator; import net.minecraft.data.loot.BlockLoot; import net.minecraft.data.loot.LootTableProvider; import net.minecraft.data.recipes.FinishedRecipe; -import net.minecraft.data.recipes.RecipeBuilder; import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.tags.BlockTagsProvider; @@ -23,13 +23,21 @@ import net.minecraft.world.item.Items; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.LootTables; import net.minecraft.world.level.storage.loot.ValidationContext; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.functions.CopyNameFunction; +import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.MatchTool; +import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider; +import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraftforge.client.model.generators.*; import net.minecraftforge.common.Tags; import net.minecraftforge.common.data.ExistingFileHelper; @@ -128,6 +136,8 @@ protected void addTranslations() { this.add("ftbsba.tooltip.fireplow", "Hold right click whilst looking at Stone to create lava"); this.add("ftbsba.tooltip.hammers", "Crushes materials down to their core components"); this.add("ftbsba.tooltip.auto-hammers", "Automatically crushes materials down using the hammer based on the tier of hammer"); + this.add("ftbsba.tooltip.energy", "Energy: %s FE"); + this.add("ftbsba.tooltip.fluid", "Fluid: %smB %s"); this.add("ftbsba.tooltip.fusing_machine", "Used to fuse items together to produce new results"); this.add("ftbsba.tooltip.super_cooler", "Used to super-cool items to produce new results"); @@ -149,6 +159,13 @@ protected void addTranslations() { } private static class SMBlockStateModels extends BlockStateProvider { + private static final List HORIZONTALS = Util.make(new ArrayList<>(), l -> { + l.add(new DirRotation(Direction.NORTH, 0)); + l.add(new DirRotation(Direction.EAST, 90)); + l.add(new DirRotation(Direction.SOUTH, 180)); + l.add(new DirRotation(Direction.WEST, 270)); + }); + private final SMBlockModels blockModels; public SMBlockStateModels(DataGenerator generator, String modid, ExistingFileHelper existingFileHelper, SMBlockModels bm) { @@ -163,25 +180,44 @@ public BlockModelProvider models() { @Override protected void registerStatesAndModels() { - Direction[] dirs = {Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST}; - int[] dirsRot = {0, 180, 270, 90}; - - List>> hammerTypes = new ArrayList<>() {{ - add(org.apache.commons.lang3.tuple.Pair.of("iron", ToolsRegistry.IRON_AUTO_HAMMER)); - add(org.apache.commons.lang3.tuple.Pair.of("gold", ToolsRegistry.GOLD_AUTO_HAMMER)); - add(org.apache.commons.lang3.tuple.Pair.of("diamond", ToolsRegistry.DIAMOND_AUTO_HAMMER)); - add(org.apache.commons.lang3.tuple.Pair.of("netherite", ToolsRegistry.NETHERITE_AUTO_HAMMER)); - }}; - - for (org.apache.commons.lang3.tuple.Pair> hammerType : hammerTypes) { - MultiPartBlockStateBuilder b = this.getMultipartBuilder(hammerType.getRight().get()); - String path = hammerType.getRight().getId().getPath(); - for (int d = 0; d < 4; d++) { - b.part().modelFile(this.models().getExistingFile(this.modLoc("block/" + path))).rotationY(dirsRot[d]).addModel().condition(AutoHammerBlock.ACTIVE, false).condition(HORIZONTAL_FACING, dirs[d]); - b.part().modelFile(this.models().getExistingFile(this.modLoc("block/" + path + "_active"))).rotationY(dirsRot[d]).addModel().condition(AutoHammerBlock.ACTIVE, true).condition(HORIZONTAL_FACING, dirs[d]); + for (var block : List.of(ToolsRegistry.IRON_AUTO_HAMMER, ToolsRegistry.GOLD_AUTO_HAMMER, ToolsRegistry.DIAMOND_AUTO_HAMMER, ToolsRegistry.NETHERITE_AUTO_HAMMER)) { + MultiPartBlockStateBuilder b = getMultipartBuilder(block.get()); + String path = block.getId().getPath(); + for (DirRotation d : HORIZONTALS) { + b.part().modelFile(models().getExistingFile(modLoc("block/" + path))) + .rotationY(d.rotation).addModel().condition(AbstractMachineBlock.ACTIVE, false) + .condition(HORIZONTAL_FACING, d.direction); + b.part().modelFile(models().getExistingFile(modLoc("block/" + path + "_active"))) + .rotationY(d.rotation).addModel().condition(AbstractMachineBlock.ACTIVE, true) + .condition(HORIZONTAL_FACING, d.direction); + } + } + + for (var block: List.of(ToolsRegistry.FUSING_MACHINE, ToolsRegistry.SUPER_COOLER)) { + var model = machineModel(block, false); + var activeModel = machineModel(block, true); + VariantBlockStateBuilder.PartialBlockstate builder = getVariantBuilder(block.get()).partialState(); + for (DirRotation d : HORIZONTALS) { + builder.with(HORIZONTAL_FACING, d.direction).with(AbstractMachineBlock.ACTIVE, false) + .setModels(new ConfiguredModel(model, 0, d.rotation, false)); + builder.with(HORIZONTAL_FACING, d.direction).with(AbstractMachineBlock.ACTIVE, true) + .setModels(new ConfiguredModel(activeModel, 0, d.rotation, false)); } + simpleBlockItem(block.get(), model); } } + + private ModelFile machineModel(RegistryObject block, boolean active) { + String name = block.getId().getPath(); + String suffix = active ? "_active" : ""; + return models().withExistingParent(name + suffix, "block/orientable") + .texture("top", modLoc("block/" + name + "_top" + suffix)) + .texture("side", modLoc("block/generic_machine_side")) + .texture("front", modLoc("block/" + name + "_front" + suffix)); + } + } + + private record DirRotation(Direction direction, int rotation) { } private static class SMBlockModels extends BlockModelProvider { @@ -376,6 +412,24 @@ protected void addTables() { dropSelf(ToolsRegistry.GOLD_AUTO_HAMMER.get()); dropSelf(ToolsRegistry.DIAMOND_AUTO_HAMMER.get()); dropSelf(ToolsRegistry.NETHERITE_AUTO_HAMMER.get()); + + preserveContents(ToolsRegistry.FUSING_MACHINE.get(), ToolsRegistry.FUSING_MACHINE_BLOCK_ENTITY.get()); + preserveContents(ToolsRegistry.SUPER_COOLER.get(), ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get()); + } + + private void preserveContents(Block block, BlockEntityType blockEntity) { + LootPool.Builder builder = LootPool.lootPool() + .when(ExplosionCondition.survivesExplosion()) + .setRolls(ConstantValue.exactly(1)) + .add(LootItem.lootTableItem(block) + .apply(CopyNameFunction.copyName(CopyNameFunction.NameSource.BLOCK_ENTITY)) + .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) + .copy("energy", "BlockEntityTag.energy", CopyNbtFunction.MergeStrategy.REPLACE) + .copy("fluid", "BlockEntityTag.fluid", CopyNbtFunction.MergeStrategy.REPLACE)) +// .apply(SetContainerContents.setContents(blockEntity) +// .withEntry(DynamicLoot.dynamicEntry(ShulkerBoxBlock.CONTENTS)))); + ); + add(block, LootTable.lootTable().withPool(builder)); } @Override diff --git a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java index fc2fbec..82a9200 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java +++ b/src/main/java/dev/ftb/ftbsba/tools/ToolsRegistry.java @@ -133,6 +133,9 @@ public ToolTipBlockItem(Block arg, Properties arg2, Component tooltip) { @Override public void appendHoverText(ItemStack arg, @Nullable Level arg2, List list, TooltipFlag arg3) { list.add(tooltip); + + // call superclass so blocks can add extra info, e.g. stored power/fluid + super.appendHoverText(arg, arg2, list, arg3); } } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlock.java index ca3312c..1175ff4 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlock.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlock.java @@ -1,6 +1,7 @@ package dev.ftb.ftbsba.tools.content.autohammer; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.item.Item; @@ -14,13 +15,11 @@ 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.material.Material; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.items.CapabilityItemHandler; import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; @@ -33,8 +32,6 @@ public class AutoHammerBlock extends Block implements EntityBlock { private final Supplier baseHammerItem; private final AutoHammerProperties props; - public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); - public static final VoxelShape EAST_WEST = Stream.of(Block.box(1, 4, 1, 15, 14, 15),Block.box(0, 4, 0, 2, 14, 2),Block.box(0, 4, 14, 2, 14, 16),Block.box(14, 4, 0, 16, 14, 2),Block.box(14, 4, 14, 16, 14, 16),Block.box(0, 0, 0, 16, 4, 16),Block.box(0, 14, 0, 16, 16, 16),Block.box(4, 4, 0, 12, 12, 2),Block.box(4, 4, 14, 12, 12, 16)).reduce((v1, v2) -> Shapes.join(v1, v2, OR)).get(); public static final VoxelShape NORTH_SOUTH = Stream.of(Block.box(1, 4, 1, 15, 14, 15),Block.box(0, 4, 14, 2, 14, 16),Block.box(14, 4, 14, 16, 14, 16),Block.box(0, 4, 0, 2, 14, 2),Block.box(14, 4, 0, 16, 14, 2),Block.box(0, 0, 0, 16, 4, 16),Block.box(0, 14, 0, 16, 16, 16),Block.box(0, 4, 4, 2, 12, 12),Block.box(14, 4, 4, 16, 12, 12)).reduce((v1, v2) -> Shapes.join(v1, v2, OR)).get(); @@ -46,12 +43,12 @@ public AutoHammerBlock(Supplier baseHammerItem, AutoHammerProperties prope this.registerDefaultState(this.getStateDefinition().any() .setValue(BlockStateProperties.HORIZONTAL_FACING, Direction.NORTH) - .setValue(ACTIVE, false)); + .setValue(AbstractMachineBlock.ACTIVE, false)); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(BlockStateProperties.HORIZONTAL_FACING, ACTIVE); + builder.add(BlockStateProperties.HORIZONTAL_FACING, AbstractMachineBlock.ACTIVE); } @Nullable diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlockEntity.java index 04aabeb..ec438dc 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/autohammer/AutoHammerBlockEntity.java @@ -1,6 +1,7 @@ package dev.ftb.ftbsba.tools.content.autohammer; import dev.ftb.ftbsba.tools.ToolsRegistry; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlock; import dev.ftb.ftbsba.tools.recipies.ToolsRecipeCache; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -17,7 +18,6 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; @@ -94,12 +94,12 @@ public static void ticker(Level level, BlockPos pos, Blo ItemStack inputStack = blockEntity.inputInventory.getStackInSlot(0); List hammerDrops = ToolsRecipeCache.getHammerDrops(level, inputStack); - boolean isActive = state.getValue(AutoHammerBlock.ACTIVE); + boolean isActive = state.getValue(AbstractMachineBlock.ACTIVE); boolean shouldBeActive = blockEntity.inputHasItemsAndOutputIsClear(hammerDrops); if (shouldBeActive && !isActive) { - level.setBlock(pos, state.setValue(AutoHammerBlock.ACTIVE, true), 3); + level.setBlock(pos, state.setValue(AbstractMachineBlock.ACTIVE, true), 3); } else if(!shouldBeActive && isActive) { - level.setBlock(pos, state.setValue(AutoHammerBlock.ACTIVE, false), 3); + level.setBlock(pos, state.setValue(AbstractMachineBlock.ACTIVE, false), 3); } if (!blockEntity.processing) { diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlock.java new file mode 100644 index 0000000..5ecef3d --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlock.java @@ -0,0 +1,159 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +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.EntityBlock; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +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.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.fluids.FluidActionResult; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.items.wrapper.PlayerInvWrapper; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public abstract class AbstractMachineBlock extends Block implements EntityBlock { + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); + + public AbstractMachineBlock() { + super(Properties.of(Material.STONE).strength(1F, 1F)); + + registerDefaultState(getStateDefinition().any() + .setValue(BlockStateProperties.HORIZONTAL_FACING, Direction.NORTH) + .setValue(ACTIVE, false)); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(BlockStateProperties.HORIZONTAL_FACING, ACTIVE); + } + + @Nullable + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List list, TooltipFlag flag) { + if (level != null) { + CompoundTag tag = stack.getTagElement("BlockEntityTag"); + if (tag != null) { + int energy = tag.getInt("energy"); + if (energy > 0) { + list.add(Component.translatable("ftbsba.tooltip.energy", energy)); + } + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(tag.getCompound("fluid")); + if (!fluidStack.isEmpty()) { + list.add(Component.translatable("ftbsba.tooltip.fluid", fluidStack.getAmount(), fluidStack.getDisplayName())); + } + } + } + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) { + if (!level.isClientSide) { + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof AbstractMachineBlockEntity machine) { + // handle filling/emptying with bucket (or other fluid containing item) + if (doFluidInteraction(machine, result.getDirection(), player, hand, true)) { + level.playSound(null, pos, SoundEvents.BUCKET_EMPTY, SoundSource.BLOCKS, 1.0f, 1.0f); + return InteractionResult.SUCCESS; + } else if (doFluidInteraction(machine, result.getDirection(), player, hand, false)) { + level.playSound(null, pos, SoundEvents.BUCKET_FILL, SoundSource.BLOCKS, 1.0f, 1.0f); + return InteractionResult.SUCCESS; + } + } + if (blockEntity instanceof MenuProvider menuProvider) { + NetworkHooks.openScreen((ServerPlayer) player, menuProvider, pos); + } + } + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level arg, BlockState arg2, BlockEntityType arg3) { + return (level1, blockPos, blockState, t) -> { + if (t instanceof AbstractMachineBlockEntity tickable) { + if (level1.isClientSide()) { + tickable.tickClient(); + } else { + tickable.tickServer(); + } + } + }; + } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean bl) { + if (state.getBlock() != newState.getBlock()) { + if (level.getBlockEntity(pos) instanceof AbstractMachineBlockEntity machine) { + machine.dropItemContents(); + } + } + + super.onRemove(state, level, pos, newState, bl); + } + + + private static boolean doFluidInteraction(BlockEntity te, Direction face, Player player, InteractionHand hand, boolean isInserting) { + ItemStack stack = player.getItemInHand(hand); + return FluidUtil.getFluidHandler(stack).map(stackHandler -> { + if (te.getCapability(ForgeCapabilities.FLUID_HANDLER, face).isPresent()) { + if (stackHandler.getTanks() == 0) return false; + int capacity = stackHandler.getTankCapacity(0); + return te.getCapability(ForgeCapabilities.FLUID_HANDLER, face).map(handler -> { + PlayerInvWrapper invWrapper = new PlayerInvWrapper(player.getInventory()); + FluidActionResult result = isInserting ? + FluidUtil.tryEmptyContainerAndStow(player.getItemInHand(hand), handler, invWrapper, capacity, player, true) : + FluidUtil.tryFillContainerAndStow(player.getItemInHand(hand), handler, invWrapper, capacity, player, true); + if (result.isSuccess()) { + player.setItemInHand(hand, result.getResult()); + return true; + } + return false; + }).orElse(false); + } + return false; + }).orElse(false); + } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + return state.setValue(BlockStateProperties.HORIZONTAL_FACING, rotation.rotate(state.getValue(BlockStateProperties.HORIZONTAL_FACING))); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + return state.rotate(mirror.getRotation(state.getValue(BlockStateProperties.HORIZONTAL_FACING))); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlockEntity.java new file mode 100644 index 0000000..c72699d --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineBlockEntity.java @@ -0,0 +1,52 @@ +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.level.block.Block; +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.minecraft.world.phys.Vec3; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.items.IItemHandler; + +public abstract class AbstractMachineBlockEntity extends BlockEntity implements MenuProvider, FluidEnergyProvider, ProgressProvider { + public AbstractMachineBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + // TODO there's a lot more we could move in here, e.g. progress ticking etc. + + public abstract ContainerData getContainerData(); + + public abstract void syncFluidTank(); + + public abstract IItemHandler getItemHandler(); + + public void tickClient() { + if (getBlockState().hasProperty(AbstractMachineBlock.ACTIVE) + && getBlockState().getValue(AbstractMachineBlock.ACTIVE) + && level.random.nextInt(5) == 0) { + Vec3 vec = Vec3.upFromBottomCenterOf(getBlockPos(), 1.05); + level.addParticle(ParticleTypes.SMOKE, vec.x, vec.y, vec.z, 0, 0, 0); + } + } + + public abstract void tickServer(); + + public void dropItemContents() { + IItemHandler handler = getItemHandler(); + for (int i = 0; i < handler.getSlots(); i++) { + Block.popResource(level, getBlockPos(), handler.getStackInSlot(i)); + } + } + + protected final void setActive(boolean active) { + boolean curActive = getBlockState().getValue(AbstractMachineBlock.ACTIVE); + if (active != curActive) { + level.setBlock(getBlockPos(), getBlockState().setValue(AbstractMachineBlock.ACTIVE, active), Block.UPDATE_CLIENTS); + } + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineMenu.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineMenu.java new file mode 100644 index 0000000..906d6eb --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/AbstractMachineMenu.java @@ -0,0 +1,139 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package dev.ftb.ftbsba.tools.content.core; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; + +import javax.annotation.Nonnull; + +public abstract class AbstractMachineMenu extends AbstractContainerMenu { + public final T blockEntity; + private int playerSlotsStart; + protected ContainerData containerData; + + public AbstractMachineMenu(MenuType type, int windowId, Inventory invPlayer, FriendlyByteBuf extraData) { + this(type, windowId, invPlayer, getTilePos(extraData)); + } + + public AbstractMachineMenu(MenuType type, int windowId, Inventory invPlayer) { + this(type, windowId, invPlayer, (BlockPos) null); + } + + public AbstractMachineMenu(MenuType type, int windowId, Inventory invPlayer, BlockPos blockPos) { + super(type, windowId); + if (blockPos != null) { + BlockEntity te0 = invPlayer.player.level.getBlockEntity(blockPos); + if (te0 instanceof AbstractMachineBlockEntity) { + //noinspection unchecked + blockEntity = (T) te0; // safe cast: T extends AbstractMachineBlockEntity, and we're doing an instanceof + containerData = blockEntity.getContainerData(); + } else { + blockEntity = null; + } + } else { + blockEntity = null; + } + } + + public static BlockPos getTilePos(FriendlyByteBuf buf) { + return buf.readBlockPos(); + } + + @Override + public void broadcastChanges() { + super.broadcastChanges(); + + if (blockEntity != null) { + blockEntity.syncFluidTank(); + } + } + + protected void addPlayerSlots(Inventory inventoryPlayer, int yOffset) { + addPlayerSlots(inventoryPlayer, 8, yOffset); + } + + protected void addPlayerSlots(Inventory inventoryPlayer, int xOffset, int yOffset) { + playerSlotsStart = slots.size(); + + // Add the player's inventory slots to the container + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 9; ++col) { + addSlot(new Slot(inventoryPlayer, col + row * 9 + 9, xOffset + col * 18, yOffset + row * 18)); + } + } + + // Add the player's action bar slots to the container + for (int hotbarIdx = 0; hotbarIdx < 9; ++hotbarIdx) { + addSlot(new Slot(inventoryPlayer, hotbarIdx, xOffset + hotbarIdx * 18, yOffset + 58)); + } + } + + @Override + @Nonnull + public ItemStack quickMoveStack(Player player, int slot) { + Slot srcSlot = slots.get(slot); + if (srcSlot == null || !srcSlot.hasItem()) { + return ItemStack.EMPTY; + } + ItemStack srcStack = srcSlot.getItem().copy(); + ItemStack copyOfSrcStack = srcStack.copy(); + + if (slot < playerSlotsStart) { + if (!moveItemStackToHotbarOrInventory(srcStack, playerSlotsStart)) + return ItemStack.EMPTY; + } else { + if (!moveItemStackTo(srcStack, 0, playerSlotsStart, false)) + return ItemStack.EMPTY; + } + + srcSlot.set(srcStack); + srcSlot.onQuickCraft(srcStack, copyOfSrcStack); + srcSlot.onTake(player, srcStack); + + return copyOfSrcStack; + } + + boolean moveItemStackToHotbarOrInventory(ItemStack stack, int startIndex) { + return moveItemStackTo(stack, startIndex + 27, startIndex + 36, false) + || moveItemStackTo(stack, startIndex, startIndex + 27, false); + } + + @Override + public boolean stillValid(Player player) { + if (blockEntity == null) { + return false; + } + Vec3 position = player.position(); + return this.blockEntity.getBlockPos().distManhattan(new Vec3i(position.x, position.y, position.z)) <= 8; + } + + public BlockEntity getBlockEntity() { + return blockEntity; + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java index b74d186..36fd67c 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/EmittingFluidTank.java @@ -1,13 +1,21 @@ package dev.ftb.ftbsba.tools.content.core; +import dev.ftb.ftbsba.tools.net.FluidTankSync; +import dev.ftb.ftbsba.tools.net.NetworkHandler; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.templates.FluidTank; +import net.minecraftforge.network.PacketDistributor; +import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; public class EmittingFluidTank extends FluidTank { private final Consumer onChange; + private boolean syncAllObservers; + private final Set toSync = Collections.newSetFromMap(new WeakHashMap<>()); public EmittingFluidTank(int capacity, Consumer onChange) { super(capacity); @@ -23,5 +31,27 @@ public EmittingFluidTank(int capacity, Predicate validator, Consumer protected void onContentsChanged() { super.onContentsChanged(); onChange.accept(this); + needSync(); + } + + public void needSync(ServerPlayer... players) { + if (players.length == 0) { + syncAllObservers = true; + } else { + toSync.addAll(Arrays.asList(players)); + } + } + + public void sync(BlockEntity blockEntity) { + FluidTankSync fluidTankSync = new FluidTankSync(blockEntity.getBlockPos(), fluid); + if (syncAllObservers) { + blockEntity.getLevel().getServer().getPlayerList().getPlayers().stream() + .filter(p -> p.containerMenu instanceof AbstractMachineMenu prov && prov.getBlockEntity() == blockEntity) + .forEach(p -> NetworkHandler.NETWORK.send(PacketDistributor.PLAYER.with(() -> p), fluidTankSync)); + } else { + toSync.forEach(p -> NetworkHandler.NETWORK.send(PacketDistributor.PLAYER.with(() -> p), fluidTankSync)); + } + syncAllObservers = false; + toSync.clear(); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java index dbaae5b..33da186 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidAndEnergyScreen.java @@ -15,13 +15,12 @@ import net.minecraft.world.inventory.InventoryMenu; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.fluids.FluidStack; -import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; public abstract class FluidAndEnergyScreen extends AbstractContainerScreen { - private int fluidXOffset; - private int progressXOffset; - private ResourceLocation texture; + private final int fluidXOffset; + private final int progressXOffset; + private final ResourceLocation texture; public FluidAndEnergyScreen(T arg, Inventory arg2, Component arg3, int fluidXOffset, int progressXOffset, ResourceLocation texture) { super(arg, arg2, arg3); @@ -38,7 +37,7 @@ public void render(PoseStack arg, int mouseX, int mouseY, float partialTicks) { arg.pushPose(); arg.translate(mouseX - 5, mouseY, 600); arg.scale(0.6F, 0.6F, 0F); - this.renderTooltip(arg, Component.literal(this.getFluidAmount() + " / " + this.getFluidCapacity() + " mB"), 0, 0); + this.renderTooltip(arg, Component.literal(this.getFluidStack().getAmount() + " / " + this.getFluidCapacity() + " mB"), 0, 0); arg.popPose(); } @@ -92,7 +91,7 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { var atlasSprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); // Fluid amount - float fluidHeight = (float) this.getFluidAmount() / this.getFluidCapacity() * 65; + float fluidHeight = (float) this.getFluidStack().getAmount() / this.getFluidCapacity() * 65; int textureHeight = 16; int tilesRequired = (int) Math.ceil(fluidHeight / textureHeight); @@ -124,7 +123,7 @@ protected void renderBg(PoseStack arg, float f, int i, int j) { arg.popPose(); // Finally, draw the progress bar - if (this.getProgressRequired() != 0) { + if (this.getProgressRequired() > 0) { float computedPercentage = (float) this.getProgress() / this.getProgressRequired() * 24; this.blit(arg, this.leftPos + this.progressXOffset, this.topPos + 28, 203, 0, (int) computedPercentage + 1, 16); } @@ -164,10 +163,8 @@ public static int[] decomposeColor(int color) { public abstract int getEnergyAmount(); public abstract int getEnergyCapacity(); - public abstract int getFluidAmount(); public abstract int getFluidCapacity(); - @Nullable public abstract FluidStack getFluidStack(); public abstract int getProgress(); diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java index feb83b2..fa861ab 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProcessorContainerData.java @@ -1,15 +1,16 @@ package dev.ftb.ftbsba.tools.content.core; import net.minecraft.world.inventory.ContainerData; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.loading.FMLEnvironment; /** * Mostly borrowed from https://github.com/desht/ModularRouters/blob/MC1.20.1-master/src/main/java/me/desht/modularrouters/block/tile/ModularRouterBlockEntity.java#L1103-L1129 with permission. * Thanks Desht! */ public class FluidEnergyProcessorContainerData implements ContainerData { + public static final int ENERGY_LO = 0; + public static final int ENERGY_HI = 1; + public static final int PROGRESS = 2; + public static final int MAX_PROGRESS = 3; private final FluidEnergyProvider fluidEnergyProvider; private final ProgressProvider progressProvider; @@ -20,43 +21,29 @@ public FluidEnergyProcessorContainerData(FluidEnergyProvider fluidEnergyProvider @Override public int get(int index) { - int result = 0; - - if (index == 0) { - result = this.fluidEnergyProvider.getEnergy() & 0x0000FFFF; - } else if (index == 1) { - result = (this.fluidEnergyProvider.getEnergy() & 0xFFFF0000) >> 16; - } else if (index == 2) { - return this.fluidEnergyProvider.getFluid(); - } else if (index == 3) { - return this.progressProvider.getProgress(); - } else if (index == 4) { - return this.progressProvider.getMaxProgress(); - } - - return result; + return switch (index) { + case ENERGY_LO -> fluidEnergyProvider.getEnergy() & 0x0000FFFF; + case ENERGY_HI -> (fluidEnergyProvider.getEnergy() & 0xFFFF0000) >> 16; + case PROGRESS -> progressProvider.getProgress(); + case MAX_PROGRESS -> progressProvider.getMaxProgress(); + default -> 0; + }; } @Override public void set(int index, int value) { - if (value < 0) value += 65536; - final int finalValue = value; + final int finalValue = value < ENERGY_LO ? value + 65536 : value; - if (index == 0) { - this.fluidEnergyProvider.setEnergy(this.fluidEnergyProvider.getEnergy() & 0xFFFF0000 | finalValue); - } else if (index == 1) { - this.fluidEnergyProvider.setEnergy(this.fluidEnergyProvider.getEnergy() & 0x0000FFFF | (finalValue << 16)); - } else if (index == 2) { - this.fluidEnergyProvider.setFluid(finalValue); - } else if (index == 3) { - this.progressProvider.setProgress(finalValue); - } else if (index == 4) { - this.progressProvider.setMaxProgress(finalValue); + switch (index) { + case ENERGY_LO -> fluidEnergyProvider.setEnergy(fluidEnergyProvider.getEnergy() & 0xFFFF0000 | finalValue); + case ENERGY_HI -> fluidEnergyProvider.setEnergy(fluidEnergyProvider.getEnergy() & 0x0000FFFF | (finalValue << 16)); + case PROGRESS -> progressProvider.setProgress(finalValue); + case MAX_PROGRESS -> progressProvider.setMaxProgress(finalValue); } } @Override public int getCount() { - return 5; + return 4; } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java index 5dffef8..99a7cc1 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/FluidEnergyProvider.java @@ -1,13 +1,16 @@ package dev.ftb.ftbsba.tools.content.core; +import net.minecraftforge.fluids.FluidStack; + public interface FluidEnergyProvider { int getEnergy(); int getMaxEnergy(); - int getFluid(); - int getMaxFluid(); + FluidStack getFluid(); - void setFluid(int fluid); + void setFluid(FluidStack fluid); + + int getMaxFluid(); void setEnergy(int energy); diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java index 4fb847e..23c4d54 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/IOStackHandler.java @@ -11,7 +11,7 @@ public class IOStackHandler implements IItemHandler { ItemStackHandler input; ItemStackHandler output; - public IOStackHandler(int inputSlots, int outputSlots, BiConsumer onChange) { + public IOStackHandler(int inputSlots, int outputSlots, BiConsumer onChange) { this.input = new EmittingStackHandler(inputSlots, (contents) -> onChange.accept(this, IO.INPUT)); this.output = new EmittingStackHandler(outputSlots, (contents) -> onChange.accept(this, IO.OUTPUT)); } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/core/RecipeCaches.java b/src/main/java/dev/ftb/ftbsba/tools/content/core/RecipeCaches.java new file mode 100644 index 0000000..edfb5b8 --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/content/core/RecipeCaches.java @@ -0,0 +1,96 @@ +package dev.ftb.ftbsba.tools.content.core; + +import dev.ftb.ftbsba.tools.recipies.FusingMachineRecipe; +import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.core.Registry; +import net.minecraft.server.packs.resources.PreparableReloadListener; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + +public class RecipeCaches { + public static final RecipeCache FUSING_MACHINE = + new RecipeCache<>((itemHandler, fluidHandler) -> hashItemHandler(itemHandler)); + public static final RecipeCache SUPER_COOLER = + new RecipeCache<>(RecipeCaches::makeSuperCoolerHash); + + private static int makeSuperCoolerHash(IItemHandler itemHandler, IFluidHandler fluidHandler) { + return Objects.hash(hashItemHandler(itemHandler), hashFluidHandler(fluidHandler)); + } + + private static int hashItemHandler(IItemHandler handler) { + IntList ids = new IntArrayList(); + for (int i = 0; i < handler.getSlots(); i++) { + ids.add(Registry.ITEM.getId(handler.getStackInSlot(i).getItem())); + } + return Arrays.hashCode(ids.intStream().sorted().toArray()); + } + + private static int hashFluidHandler(IFluidHandler handler) { + IntList ids = new IntArrayList(); + for (int i = 0; i < handler.getTanks(); i++) { + ids.add(Registry.FLUID.getId(handler.getFluidInTank(i).getFluid())); + } + return Arrays.hashCode(ids.intStream().sorted().toArray()); + } + + public static void clearAll() { + FUSING_MACHINE.clear(); + SUPER_COOLER.clear(); + } + + public static class ReloadListener implements PreparableReloadListener { + @Override + public CompletableFuture reload(PreparationBarrier stage, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { + return CompletableFuture.runAsync(RecipeCaches::clearAll, gameExecutor) + .thenCompose(stage::wait); + } + } + + public static class RecipeCache> { + private static final int MAX_CACHE_SIZE = 1024; + + private final KeyGen keyGen; + private final Int2ObjectLinkedOpenHashMap> recipeCache = new Int2ObjectLinkedOpenHashMap<>(MAX_CACHE_SIZE, 0.25f); + + public RecipeCache(KeyGen keyGen) { + this.keyGen = keyGen; + } + + public Optional getCachedRecipe(Supplier> recipeFinder, IItemHandler itemHandler, IFluidHandler fluidHandler) { + int key = keyGen.genHashKey(itemHandler, fluidHandler); + + if (recipeCache.containsKey(key)) { + return recipeCache.getAndMoveToFirst(key); + } else { + Optional newRecipe = recipeFinder.get(); + while (recipeCache.size() >= MAX_CACHE_SIZE) { + recipeCache.removeLast(); + } + recipeCache.put(key, newRecipe); + return newRecipe; + } + } + + private void clear() { + recipeCache.clear(); + } + + @FunctionalInterface + public interface KeyGen { + int genHashKey(IItemHandler itemHandler, IFluidHandler fluidHandler); + } + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java index 5df6ca4..8572339 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlock.java @@ -1,62 +1,15 @@ package dev.ftb.ftbsba.tools.content.fusion; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlock; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -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.material.Material; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.network.NetworkHooks; import org.jetbrains.annotations.Nullable; -public class FusingMachineBlock extends Block implements EntityBlock { - public FusingMachineBlock() { - super(Properties.of(Material.STONE).strength(1F, 1F)); - } - - @Override - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) { - if (level.isClientSide) { - return InteractionResult.SUCCESS; - } - - NetworkHooks.openScreen((ServerPlayer) player, (FusingMachineBlockEntity) level.getBlockEntity(pos), pos); - return InteractionResult.SUCCESS; - } - +public class FusingMachineBlock extends AbstractMachineBlock { @Nullable @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new FusingMachineBlockEntity(pos, state); } - - @Nullable - @Override - public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { - return FusingMachineBlockEntity::ticker; - } - - @Override - public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) { - super.onRemove(arg, arg2, arg3, arg4, bl); - - BlockEntity entity = arg2.getBlockEntity(arg3); - if (!(entity instanceof FusingMachineBlockEntity fusingBlockEntity)) { - return; - } - - fusingBlockEntity.input.ifPresent(handler -> { - for (int i = 0; i < handler.getSlots(); i++) { - Block.popResource(arg2, arg3, handler.getStackInSlot(i)); - } - }); - } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java index 4ce1e3e..3a7ea59 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineBlockEntity.java @@ -3,104 +3,94 @@ import dev.ftb.ftbsba.tools.ToolsRegistry; import dev.ftb.ftbsba.tools.content.core.*; import dev.ftb.ftbsba.tools.recipies.FusingMachineRecipe; -import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.world.MenuProvider; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.templates.FluidTank; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.util.List; +import java.util.Optional; import java.util.function.Consumer; -public class FusingMachineBlockEntity extends BlockEntity implements MenuProvider, FluidEnergyProvider, ProgressProvider { - public LazyOptional energy = LazyOptional.of(() -> new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged())); - public LazyOptional tank = LazyOptional.of(() -> new ExtractOnlyFluidTank(10000, (tank) -> this.setChanged())); - public LazyOptional input = LazyOptional.of(() -> new EmittingStackHandler(2, (contents) -> { +public class FusingMachineBlockEntity extends AbstractMachineBlockEntity { + private final EmittingEnergy energyHandler = new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged()); + private final ExtractOnlyFluidTank fluidHandler = new ExtractOnlyFluidTank(10000, (tank) -> this.setChanged()); + private final EmittingStackHandler itemHandler = new EmittingStackHandler(2, (contents) -> { this.setChanged(); this.progress = 0; - })); + }); - public int progress = 0; - public int progressRequired = 0; + private final LazyOptional energy = LazyOptional.of(() -> energyHandler); + private final LazyOptional tank = LazyOptional.of(() -> fluidHandler); + private final LazyOptional input = LazyOptional.of(() -> itemHandler); - public FusingMachineRecipe currentRecipe = null; - - FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); + private int progress = 0; + private int progressRequired = 0; + private FusingMachineRecipe currentRecipe = null; + private final FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); public FusingMachineBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.FUSING_MACHINE_BLOCK_ENTITY.get(), pos, state); } - public static void ticker(Level level, BlockPos pos, BlockState state, T t) { - if (!(t instanceof FusingMachineBlockEntity entity)) { - return; - } - - if (level.isClientSide) { - return; - } - - // Requires input items, energy and the fluid tank to be not full and the correct fluid for the recipe - if (!entity.hasEnergy() || !entity.hasOccupiedInputSlots()) { + @Override + public void tickServer() { + if (!hasEnergy() || !hasOccupiedInputSlots()) { return; } // We need to find the recipe before we can check the fluid tank - if (entity.progress == 0) { - var recipe = entity.testForRecipe(); - if (recipe == null) { - return; - } + if (progress == 0) { + currentRecipe = RecipeCaches.FUSING_MACHINE.getCachedRecipe(this::findValidRecipe, itemHandler, null) + .orElse(null); + + if (currentRecipe != null) { + // Test for tank validity + // TODO: Add fluid check + var tank = fluidHandler; + if (!tank.isEmpty() && !tank.getFluid().isFluidEqual(currentRecipe.fluidResult)) { + setActive(false); + return; + } - // Test for tank validity - // TODO: Add fluid check - var tank = entity.tank.orElseThrow(RuntimeException::new); - if (!tank.isEmpty() && !tank.getFluid().isFluidEqual(recipe.fluidResult)) { - return; - } + // Otherwise the fluid is either empty or the same as the recipe + if (!tank.isEmpty() && tank.getFluid().getAmount() + currentRecipe.fluidResult.getAmount() > tank.getCapacity()) { + // Don't allow the fluid to overflow + setActive(false); + return; + } - // Otherwise the fluid is either empty or the same as the recipe - if (!tank.isEmpty() && tank.getFluid().getAmount() + recipe.fluidResult.getAmount() > tank.getCapacity()) { - // Don't allow the fluid to overflow - return; + // Finally, we can start the process + progressRequired = currentRecipe.energyComponent.ticksToProcess(); + progress = 1; // Start the progress + } else { + setActive(false); } - - // Finally, we can start the process - entity.progressRequired = recipe.energyComponent.ticksToProcess(); - entity.progress = 1; // Start the progress - entity.currentRecipe = recipe; } - if (entity.currentRecipe != null) { - if (entity.progress == entity.progressRequired) { - // We're done... Ouput the result - entity.extractRecipe(); - entity.breakProgress(); + if (currentRecipe != null) { + if (progress == progressRequired) { + // We're done... Output the result + extractRecipe(); + breakProgress(); } else { - entity.useEnergy(); - entity.progress ++; + setActive(true); + useEnergy(); + progress ++; } } } @@ -108,18 +98,17 @@ public static void ticker(Level level, BlockPos pos, Blo //#region BlockEntity processing private void extractRecipe() { - var inventory = input.orElseThrow(RuntimeException::new); - var tank = this.tank.orElseThrow(RuntimeException::new); + var inventory = itemHandler; var requiredItems = this.currentRecipe.ingredients; // Try and remove the items from the input slots for (var ingredient : requiredItems) { for (int i = 0; i < inventory.getSlots(); i++) { - var stack = inventory.getStackInSlot(i); - if (ingredient.test(stack)) { - var result = inventory.extractItem(i, 1, true); - if (result.isEmpty()) { + if (ingredient.test(inventory.getStackInSlot(i))) { + if (inventory.extractItem(i, 1, true).isEmpty()) { + // this shouldn't happen, but let's be defensive breakProgress(); + currentRecipe = null; return; } } @@ -128,15 +117,14 @@ private void extractRecipe() { for (var ingredient : requiredItems) { for (int i = 0; i < inventory.getSlots(); i++) { - var stack = inventory.getStackInSlot(i); - if (ingredient.test(stack)) { + if (ingredient.test(inventory.getStackInSlot(i))) { // This logically can't be false due to the simulation above inventory.extractItem(i, 1, false); } } } - tank.forceFill(this.currentRecipe.fluidResult, IFluidHandler.FluidAction.EXECUTE); + fluidHandler.forceFill(this.currentRecipe.fluidResult, IFluidHandler.FluidAction.EXECUTE); } private void useEnergy() { @@ -144,101 +132,61 @@ private void useEnergy() { return; } - if (!this.energy.isPresent()) { - breakProgress(); - return; - } - - EmittingEnergy emittingEnergy = this.energy.orElseThrow(RuntimeException::new); - var result = emittingEnergy.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), true); + var result = energyHandler.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), true); if (result < this.currentRecipe.energyComponent.fePerTick()) { breakProgress(); return; } - emittingEnergy.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), false); + energyHandler.extractEnergy(this.currentRecipe.energyComponent.fePerTick(), false); } private void breakProgress() { this.progress = 0; this.progressRequired = 0; - this.currentRecipe = null; } private boolean hasEnergy() { - return energy.map(EmittingEnergy::getEnergyStored).orElse(0) > 0; + return energyHandler.getEnergyStored() > 0; } private boolean hasOccupiedInputSlots() { - if (!input.isPresent()) { - return false; - } - - var hasItems = false; - var handler = input.orElseThrow(RuntimeException::new); - - for (int i = 0; i < handler.getSlots(); i++) { - if (!handler.getStackInSlot(i).isEmpty()) { - hasItems = true; - break; + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) { + return true; } } - - return hasItems; + return false; } - @Nullable - private FusingMachineRecipe testForRecipe() { - if (!input.isPresent()) { - return null; - } - - - var handler = input.orElseThrow(RuntimeException::new); - - // This is an immutable hash map so the lookup is fast - var recipes = level.getRecipeManager().getAllRecipesFor(ToolsRegistry.FUSING_MACHINE_RECIPE_TYPE.get()); - - if (recipes.isEmpty()) { - return null; - } - - for (var recipe : recipes) { - List ingredients = recipe.ingredients.stream().filter(ingredient -> !ingredient.isEmpty()).toList(); - - NonNullList foundItems = NonNullList.create(); - for (int i = 0; i < handler.getSlots(); i++) { - if (handler.getStackInSlot(i).isEmpty()) { - // Don't waste time checking empty slots - continue; - } + private Optional findValidRecipe() { + return level.getRecipeManager().getAllRecipesFor(ToolsRegistry.FUSING_MACHINE_RECIPE_TYPE.get()).stream() + .filter(this::recipeMatchesInput) + .findFirst(); + } - for (Ingredient ingredient : ingredients) { - if (ingredient.test(handler.getStackInSlot(i))) { - foundItems.add(ingredient); + private boolean recipeMatchesInput(FusingMachineRecipe recipe) { + NonNullList foundIngredients = NonNullList.create(); + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) { + for (Ingredient ingredient : recipe.ingredients) { + if (ingredient.test(itemHandler.getStackInSlot(i))) { + foundIngredients.add(ingredient); } } } - - for (var ingredient : recipe.ingredients) { - if (!foundItems.contains(ingredient)) { - return null; - } - } - - return recipe; } - return null; + return foundIngredients.containsAll(recipe.ingredients); } - //#endregion +//#endregion - //#region BlockEntity setup and syncing +//#region BlockEntity setup and syncing @Override public Component getDisplayName() { - return Component.translatable("container.ftbsba.fusing_machine"); // TODO: Add translation + return Component.translatable("container.ftbsba.fusing_machine"); } @Override @@ -257,25 +205,28 @@ public Component getDisplayName() { @Nullable @Override public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { - return new FusingMachineContainer(i, containerData, arg, arg2, this); + if (arg2 instanceof ServerPlayer sp) { + fluidHandler.needSync(sp); + } + return new FusingMachineContainer(i, arg, getBlockPos()); } @Override public void load(CompoundTag arg) { super.load(arg); - input.ifPresent(input -> input.deserializeNBT(arg.getCompound("input"))); - energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); - tank.ifPresent(tank -> tank.readFromNBT(arg.getCompound("fluid"))); + itemHandler.deserializeNBT(arg.getCompound("input")); + energyHandler.deserializeNBT(arg.get("energy")); + fluidHandler.readFromNBT(arg.getCompound("fluid")); } @Override protected void saveAdditional(CompoundTag arg) { super.saveAdditional(arg); - input.ifPresent(input -> arg.put("input",input.serializeNBT())); - energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); - tank.ifPresent(tank -> arg.put("fluid", tank.writeToNBT(new CompoundTag()))); + arg.put("input", itemHandler.serializeNBT()); + arg.put("energy", energyHandler.serializeNBT()); + arg.put("fluid", fluidHandler.writeToNBT(new CompoundTag())); } @Override @@ -286,11 +237,6 @@ public void invalidateCaps() { tank.invalidate(); } - @Override - public ClientboundBlockEntityDataPacket getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this, entity -> this.getUpdateTag()); - } - @Override public CompoundTag getUpdateTag() { CompoundTag compoundTag = new CompoundTag(); @@ -304,43 +250,38 @@ public void handleUpdateTag(CompoundTag tag) { load(tag); } - @Override - public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { - load(pkt.getTag()); - } - - //#endregion +//#endregion - //#region Data Syncing helper methods +//#region Data Syncing helper methods @Override public int getEnergy() { - return energy.map(EmittingEnergy::getEnergyStored).orElse(0); + return energyHandler.getEnergyStored(); } @Override public int getMaxEnergy() { - return energy.map(EmittingEnergy::getMaxEnergyStored).orElse(0); + return energyHandler.getMaxEnergyStored(); } @Override - public int getFluid() { - return tank.map(IFluidTank::getFluidAmount).orElse(0); + public FluidStack getFluid() { + return fluidHandler.getFluid(); } @Override public int getMaxFluid() { - return tank.map(IFluidTank::getCapacity).orElse(0); + return fluidHandler.getCapacity(); } @Override - public void setFluid(int fluid) { - tank.ifPresent(t -> t.overrideFluidAmount(fluid)); + public void setFluid(FluidStack fluid) { + fluidHandler.overrideFluidStack(fluid); } @Override public void setEnergy(int energy) { - this.energy.ifPresent(e -> e.overrideEnergy(energy)); + energyHandler.overrideEnergy(energy); } @Override @@ -363,7 +304,22 @@ public void setMaxProgress(int maxProgress) { this.progressRequired = maxProgress; } - //#endregion + @Override + public EmittingStackHandler getItemHandler() { + return itemHandler; + } + + @Override + public ContainerData getContainerData() { + return containerData; + } + + @Override + public void syncFluidTank() { + fluidHandler.sync(this); + } + +//#endregion public static class ExtractOnlyFluidTank extends EmittingFluidTank { public ExtractOnlyFluidTank(int capacity, Consumer listener) { @@ -379,12 +335,8 @@ public int forceFill(FluidStack resource, FluidAction action) { return super.fill(resource, action); } - public void overrideFluidAmount(int amount) { - if (this.fluid.isEmpty()) { - return; - } - - this.fluid.setAmount(amount); + public void overrideFluidStack(FluidStack stack) { + this.fluid = stack; } } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java index cea8eb4..8cfa9dd 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineContainer.java @@ -1,104 +1,25 @@ package dev.ftb.ftbsba.tools.content.fusion; import dev.ftb.ftbsba.tools.ToolsRegistry; -import dev.ftb.ftbsba.tools.content.supercooler.SuperCoolerBlockEntity; -import net.minecraft.client.gui.screens.inventory.ContainerScreen; -import net.minecraft.core.Vec3i; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineMenu; +import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.items.SlotItemHandler; -import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; - -public class FusingMachineContainer extends AbstractContainerMenu { - FusingMachineBlockEntity entity; - ContainerData containerData; - - protected FusingMachineContainer(int i, ContainerData data, Inventory arg, Player arg2, FusingMachineBlockEntity entity) { - super(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), i); - - addPlayerSlots(arg, 8, 56, this::addSlot); - - this.entity = entity; - this.entity.input.ifPresent(itemHandler -> { - addSlot(new SlotItemHandler(itemHandler, 0, 43, 27)); - addSlot(new SlotItemHandler(itemHandler, 1, 43 + 18, 27)); - }); - - this.containerData = data; - addDataSlots(data); - } - - public FusingMachineContainer(int i, Inventory arg, FriendlyByteBuf arg2) { - this(i, arg, arg.player, (FusingMachineBlockEntity) arg.player.level.getBlockEntity(arg2.readBlockPos())); - } - - public FusingMachineContainer(int i, Inventory arg, Player player, FusingMachineBlockEntity entity) { - this(i, entity.containerData, arg, player, entity); +public class FusingMachineContainer extends AbstractMachineMenu { + public FusingMachineContainer(int windowId, Inventory playerInventory, FriendlyByteBuf buffer) { + this(windowId, playerInventory, getTilePos(buffer)); } - @Override - public ItemStack quickMoveStack(Player arg, int index) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.slots.get(index); - - if (slot != null && slot.hasItem()) { - ItemStack currentStack = slot.getItem(); - itemstack = currentStack.copy(); - - if (index > 35) { - if (!this.moveItemStackTo(currentStack, 0, 36, false)) { - return ItemStack.EMPTY; - } - } else if (!this.moveItemStackTo(currentStack, 36, 38, false)) { - return ItemStack.EMPTY; - } - - if (currentStack.isEmpty()) { - slot.set(ItemStack.EMPTY); - } else { - slot.setChanged(); - } - } + public FusingMachineContainer(int windowId, Inventory playerInventory, BlockPos pos) { + super(ToolsRegistry.FUSING_MACHINE_CONTAINER.get(), windowId, playerInventory, pos); - return itemstack; - } - - @Override - public boolean stillValid(Player arg) { - Vec3 position = arg.position(); - return this.entity.getBlockPos().distManhattan(new Vec3i(position.x, position.y, position.z)) <= 8; - } + addSlot(new SlotItemHandler(blockEntity.getItemHandler(), 0, 43, 27)); + addSlot(new SlotItemHandler(blockEntity.getItemHandler(), 1, 43 + 18, 27)); - @Override - public void slotsChanged(Container arg) { - super.slotsChanged(arg); - this.entity.setChanged(); - } + addPlayerSlots(playerInventory, 8, 84); - public static void addPlayerSlots(Inventory playerInventory, int inX, int inY, Consumer addSlot) { - // Slots for the hotbar - for (int row = 0; row < 9; ++ row) { - int x = inX + row * 18; - int y = inY + 86; - addSlot.accept(new Slot(playerInventory, row, x, y)); - } - // Slots for the main inventory - for (int row = 1; row < 4; ++ row) { - for (int col = 0; col < 9; ++ col) { - int x = inX + col * 18; - int y = row * 18 + (inY + 10); - addSlot.accept(new Slot(playerInventory, col + row * 9, x, y)); - } - } + addDataSlots(containerData); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java index 2116a91..48cdf07 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/fusion/FusingMachineScreen.java @@ -6,9 +6,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; -import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; import org.jetbrains.annotations.Nullable; public class FusingMachineScreen extends FluidAndEnergyScreen { @@ -29,37 +27,31 @@ protected void renderLabels(PoseStack arg, int i, int j) { @Override public int getEnergyAmount() { - var data = this.menu.containerData; - return (data.get(0) & 0xFFFF) | (data.get(1) << 16); + return menu.blockEntity.getEnergy(); } @Override public int getEnergyCapacity() { - return this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); - } - - @Override - public int getFluidAmount() { - return this.menu.containerData.get(2); + return this.menu.blockEntity.getMaxEnergy(); } @Override public int getFluidCapacity() { - return this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); + return this.menu.blockEntity.getMaxFluid(); } @Override public @Nullable FluidStack getFluidStack() { - return this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); + return this.menu.blockEntity.getFluid(); } @Override public int getProgress() { - return this.menu.containerData.get(3); + return this.menu.blockEntity.getProgress(); } @Override public int getProgressRequired() { - return this.menu.containerData.get(4); + return menu.blockEntity.getMaxProgress(); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java index 36344a0..b8a6c21 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlock.java @@ -1,63 +1,15 @@ package dev.ftb.ftbsba.tools.content.supercooler; -import dev.ftb.ftbsba.tools.content.fusion.FusingMachineBlockEntity; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlock; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -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.material.Material; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.network.NetworkHooks; import org.jetbrains.annotations.Nullable; -public class SuperCoolerBlock extends Block implements EntityBlock { - public SuperCoolerBlock() { - super(Properties.of(Material.STONE).strength(1F, 1F)); - } - - @Override - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) { - if (level.isClientSide) { - return InteractionResult.SUCCESS; - } - - NetworkHooks.openScreen((ServerPlayer) player, (SuperCoolerBlockEntity) level.getBlockEntity(pos), pos); - return InteractionResult.SUCCESS; - } - +public class SuperCoolerBlock extends AbstractMachineBlock { @Nullable @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new SuperCoolerBlockEntity(pos, state); } - - @Nullable - @Override - public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType entityType) { - return SuperCoolerBlockEntity::ticker; - } - - @Override - public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) { - super.onRemove(arg, arg2, arg3, arg4, bl); - - BlockEntity entity = arg2.getBlockEntity(arg3); - if (!(entity instanceof SuperCoolerBlockEntity superCoolerEntity)) { - return; - } - - superCoolerEntity.ioWrapper.ifPresent(handler -> { - for (int i = 0; i < handler.getSlots(); i++) { - Block.popResource(arg2, arg3, handler.getStackInSlot(i)); - } - }); - } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java index 9f56fcf..2c696ec 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerBlockEntity.java @@ -3,99 +3,114 @@ import dev.ftb.ftbsba.tools.ToolsRegistry; import dev.ftb.ftbsba.tools.content.core.*; import dev.ftb.ftbsba.tools.recipies.SuperCoolerRecipe; +import net.minecraft.ResourceLocationException; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.templates.FluidTank; +import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SuperCoolerBlockEntity extends BlockEntity implements MenuProvider, ProgressProvider, FluidEnergyProvider { +import java.util.Optional; + +public class SuperCoolerBlockEntity extends AbstractMachineBlockEntity { private static final Logger LOGGER = LoggerFactory.getLogger(SuperCoolerBlockEntity.class); - public LazyOptional energy = LazyOptional.of(() -> new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged())); - public LazyOptional tank = LazyOptional.of(() -> new EmittingFluidTank(10000, (tank) -> this.setChanged())); - public LazyOptional ioWrapper = LazyOptional.of(() -> new IOStackHandler(3, 1, (container, ioType) -> { + private final EmittingEnergy energyHandler = new EmittingEnergy(100000, 10000, 10000, (energy) -> this.setChanged()); + private final EmittingFluidTank fluidHandler = new EmittingFluidTank(10000, (tank) -> this.setChanged()); + private final IOStackHandler itemHandler = new IOStackHandler(3, 1, (container, ioType) -> { setChanged(); if (ioType == IOStackHandler.IO.INPUT) { if (this.progress > 0) { this.progress = 0; } } - })); + }); + + private final LazyOptional energy = LazyOptional.of(() -> energyHandler); + private final LazyOptional tank = LazyOptional.of(() -> fluidHandler); + private final LazyOptional ioWrapper = LazyOptional.of(() -> itemHandler); - FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); + private final FluidEnergyProcessorContainerData containerData = new FluidEnergyProcessorContainerData(this, this); - int progress = 0; - int progressRequired = 0; - SuperCoolerRecipe processingRecipe = null; + private int progress = 0; + private int progressRequired = 0; + private SuperCoolerRecipe processingRecipe = null; + private ResourceLocation pendingRecipeId = null; // set when loading from NBT boolean tickLock = false; public SuperCoolerBlockEntity(BlockPos pos, BlockState state) { super(ToolsRegistry.SUPER_COOLER_BLOCK_ENTITY.get(), pos, state); } - public static void ticker(Level level, BlockPos pos, BlockState state, T t) { - if (!(t instanceof SuperCoolerBlockEntity entity)) { + @Override + public IOStackHandler getItemHandler() { + return itemHandler; + } + + @Override + public void tickServer() { + if (tickLock) { return; } - if (level.isClientSide || entity.tickLock) { + if (!hasEnergy() || !hasFluid() || !hasItemInAnySlot()) { + setActive(false); + progress = 0; return; } - if (!entity.hasEnergy() || !entity.hasFluid() || !entity.hasItemInAnySlot()) { - entity.progress = 0; - return; + if (pendingRecipeId != null) { + level.getServer().getRecipeManager().byKey(pendingRecipeId).ifPresent(r -> { + if (r instanceof SuperCoolerRecipe s) { + processingRecipe = s; + } + }); + pendingRecipeId = null; } - // We should test for the recipe here - if (entity.progress == 0) { - SuperCoolerRecipe recipe = entity.testForRecipe(); - if (recipe == null) { - return; - } + if (progress == 0) { + processingRecipe = RecipeCaches.SUPER_COOLER.getCachedRecipe(this::findValidRecipe, itemHandler, fluidHandler) + .orElse(null); - if (!entity.canAcceptOutput(recipe)) { + if (processingRecipe == null || !canAcceptOutput(processingRecipe)) { + setActive(false); return; } - entity.progress = 1; - entity.processingRecipe = recipe; - entity.progressRequired = recipe.energyComponent.ticksToProcess(); + progress = 1; + progressRequired = processingRecipe.energyComponent.ticksToProcess(); } - if (entity.processingRecipe != null) { - if (entity.progress == entity.progressRequired) { - entity.executeRecipe(); + if (processingRecipe != null) { + if (progress == progressRequired) { + executeRecipe(); } else { - // Use energy - entity.useEnergy(); - entity.progress++; + if (fluidHandler.getFluid().containsFluid(processingRecipe.fluidIngredient)) { + // Use energy + setActive(true); + useEnergy(); + progress++; + } } } } @@ -106,27 +121,21 @@ public void executeRecipe() { return; } - // This shouldn't be possible, but we'll check because we have to - var tank = this.tank.orElseThrow(RuntimeException::new); - var ioWrapper = this.ioWrapper.orElseThrow(RuntimeException::new); + ItemStackHandler input = itemHandler.getInput(); - // Extract the fluid - int requiredFluid = this.processingRecipe.fluidIngredient.getAmount(); - var fluidResult = tank.drain(requiredFluid, IFluidHandler.FluidAction.SIMULATE); - if (fluidResult.isEmpty() || fluidResult.getAmount() < requiredFluid) { + // Ensure enough fluid + if (!fluidHandler.getFluid().containsFluid(processingRecipe.fluidIngredient)) { breakProgress(); return; } - // Extract the items + // Ensure the items are OK // First test if we can extract the items by simulating and validating the result var requiredItems = this.processingRecipe.ingredients; for (var ingredient : requiredItems) { - for (int i = 0; i < ioWrapper.getInput().getSlots(); i++) { - var stack = ioWrapper.getInput().getStackInSlot(i); - if (ingredient.test(stack)) { - var result = ioWrapper.getInput().extractItem(i, 1, true); - if (result.isEmpty()) { + for (int i = 0; i < input.getSlots(); i++) { + if (ingredient.test(input.getStackInSlot(i))) { + if (input.extractItem(i, 1, true).isEmpty()) { breakProgress(); return; } @@ -134,20 +143,19 @@ public void executeRecipe() { } } - // Do everything - tank.drain(requiredFluid, IFluidHandler.FluidAction.EXECUTE); + // Consume the inputs + fluidHandler.drain(processingRecipe.fluidIngredient.getAmount(), IFluidHandler.FluidAction.EXECUTE); for (var ingredient : requiredItems) { - for (int i = 0; i < ioWrapper.getInput().getSlots(); i++) { - var stack = ioWrapper.getInput().getStackInSlot(i); - if (ingredient.test(stack)) { + for (int i = 0; i < input.getSlots(); i++) { + if (ingredient.test(input.getStackInSlot(i))) { // This logically can't be false due to the simulation above - ioWrapper.getInput().extractItem(i, 1, false); + input.extractItem(i, 1, false); } } } // Produce the result - ioWrapper.getOutput().insertItem(0, this.processingRecipe.result.copy(), false); + itemHandler.getOutput().insertItem(0, this.processingRecipe.result.copy(), false); breakProgress(); } @@ -156,19 +164,13 @@ private void useEnergy() { return; } - if (!this.energy.isPresent()) { - breakProgress(); - return; - } - - EmittingEnergy emittingEnergy = this.energy.orElseThrow(RuntimeException::new); - var result = emittingEnergy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), true); + var result = energyHandler.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), true); if (result < this.processingRecipe.energyComponent.fePerTick()) { breakProgress(); return; } - emittingEnergy.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), false); + energyHandler.extractEnergy(this.processingRecipe.energyComponent.fePerTick(), false); } /** @@ -182,8 +184,7 @@ private void breakProgress() { } public boolean canAcceptOutput(SuperCoolerRecipe recipe) { - var output = this.ioWrapper.orElseThrow(RuntimeException::new).getOutput(); - var outputSlot = output.getStackInSlot(0); + var outputSlot = itemHandler.getOutput().getStackInSlot(0); if (outputSlot.isEmpty()) { return true; @@ -195,23 +196,19 @@ public boolean canAcceptOutput(SuperCoolerRecipe recipe) { } // Are the items the same? - return outputSlot.sameItem(recipe.result); + return ItemHandlerHelper.canItemStacksStack(outputSlot, recipe.result); } private boolean hasFluid() { - return tank.map(IFluidTank::getFluid).map(e -> !e.isEmpty()).orElse(false); + return !fluidHandler.isEmpty(); } private boolean hasEnergy() { - return energy.map(IEnergyStorage::getEnergyStored).orElse(0) > 0; + return energyHandler.getEnergyStored() > 0; } private boolean hasItemInAnySlot() { - if (!ioWrapper.isPresent()) { - return true; - } - - var input = ioWrapper.orElseThrow(RuntimeException::new).getInput(); + var input = itemHandler.getInput(); for (int i = 0; i < input.getSlots(); i++) { if (!input.getStackInSlot(i).isEmpty()) { return true; @@ -221,81 +218,29 @@ private boolean hasItemInAnySlot() { return false; } - /** - * Concerned this is too complex for a per tick operation. - * @return The recipe to process, or null if no recipe can be processed - */ - @Nullable - private SuperCoolerRecipe testForRecipe() { - LazyOptional ioWrapper = this.ioWrapper; - if (!ioWrapper.isPresent()) { - return null; - } - - // Does this cache? I haven't looked yet - var recipes = this.level.getServer().getRecipeManager().getAllRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get()); - if (recipes.isEmpty()) { - return null; - } - - if (!this.tank.isPresent()) { - return null; - } - - if (!this.ioWrapper.isPresent()) { - return null; - } - - var io = ioWrapper.orElseThrow(RuntimeException::new); - boolean hasOccupiedSlot = false; - for (int i = 0; i < io.getInput().getSlots(); i++) { - if (!io.getInput().getStackInSlot(i).isEmpty()) { - hasOccupiedSlot = true; - break; - } - } + private Optional findValidRecipe() { + return level.getRecipeManager().getAllRecipesFor(ToolsRegistry.SUPER_COOLER_RECIPE_TYPE.get()).stream() + .filter(this::recipeMatchesInput) + .findFirst(); + } - // No items in the input slots = no recipe - if (!hasOccupiedSlot) { - return null; + private boolean recipeMatchesInput(SuperCoolerRecipe recipe) { + if (!recipe.fluidIngredient.isFluidEqual(fluidHandler.getFluid())) { + return false; } - var recipesForFluid = recipes.stream() - .filter(e -> !e.fluidIngredient.isEmpty()) - .filter(e -> e.fluidIngredient.isFluidEqual(this.tank.orElseThrow(RuntimeException::new).getFluid())) - .filter(e -> e.fluidIngredient.getAmount() <= this.tank.orElseThrow(RuntimeException::new).getFluidAmount()) - .toList(); - - for (var recipe : recipesForFluid) { - ItemStackHandler input = io.getInput(); - - var filledIngredients = recipe.ingredients.stream().filter(e -> !e.isEmpty()).toList(); - NonNullList foundIngredients = NonNullList.create(); - - for (int i = 0; i < input.getSlots(); i++) { - var stack = input.getStackInSlot(i); - if (stack.isEmpty()) { - continue; - } - - for (var ingredient : filledIngredients) { - if (ingredient.test(stack)) { + NonNullList foundIngredients = NonNullList.create(); + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) { + for (Ingredient ingredient : recipe.ingredients) { + if (ingredient.test(itemHandler.getStackInSlot(i))) { foundIngredients.add(ingredient); } } } - - // Compare the found ingredients to the recipe ingredients - for (var ingredient : recipe.ingredients) { - if (!foundIngredients.contains(ingredient)) { - return null; - } - } - - return recipe; } - return null; + return foundIngredients.containsAll(recipe.ingredients); } @Override @@ -319,7 +264,7 @@ public Component getDisplayName() { @Nullable @Override public AbstractContainerMenu createMenu(int i, Inventory arg, Player arg2) { - return new SuperCoolerContainer(i, containerData, arg, arg2, this); + return new SuperCoolerContainer(i, arg, getBlockPos()); } @Override @@ -334,12 +279,10 @@ public void invalidateCaps() { public void load(CompoundTag arg) { super.load(arg); - ioWrapper.ifPresent(wrapper -> { - wrapper.getInput().deserializeNBT(arg.getCompound("input")); - wrapper.getInput().deserializeNBT(arg.getCompound("output")); - }); - energy.ifPresent(storage -> storage.deserializeNBT(arg.get("energy"))); - tank.ifPresent(tank -> ((FluidTank) tank).readFromNBT(arg.getCompound("fluid"))); + itemHandler.getInput().deserializeNBT(arg.getCompound("input")); + itemHandler.getOutput().deserializeNBT(arg.getCompound("output")); + energyHandler.deserializeNBT(arg.get("energy")); + fluidHandler.readFromNBT(arg.getCompound("fluid")); // Write the progress this.progress = arg.getInt("progress"); @@ -348,20 +291,9 @@ public void load(CompoundTag arg) { // Write the recipe id if (arg.contains("recipe")) { try { - Recipe parsedRecipe = this.level.getServer().getRecipeManager().byKey(new ResourceLocation(arg.getString("recipe"))).orElse(null); - if (parsedRecipe == null) { - this.processingRecipe = null; - this.progress = 0; - this.progressRequired = 0; - return; - } - - this.processingRecipe = (SuperCoolerRecipe) parsedRecipe; // Try catch just in case - } catch (Exception e) { - LOGGER.error("Failed to load recipe from NBT", e); - this.processingRecipe = null; - this.progress = 0; - this.progressRequired = 0; + pendingRecipeId = new ResourceLocation(arg.getString("recipe")); + } catch (ResourceLocationException e) { + pendingRecipeId = null; } } } @@ -370,12 +302,10 @@ public void load(CompoundTag arg) { protected void saveAdditional(CompoundTag arg) { super.saveAdditional(arg); - ioWrapper.ifPresent(wrapper -> { - arg.put("input", wrapper.getInput().serializeNBT()); - arg.put("output", wrapper.getInput().serializeNBT()); - }); - energy.ifPresent(storage -> arg.put("energy", storage.serializeNBT())); - tank.ifPresent(tank -> arg.put("fluid", ((FluidTank) tank).writeToNBT(new CompoundTag()))); + arg.put("input", itemHandler.getInput().serializeNBT()); + arg.put("output", itemHandler.getOutput().serializeNBT()); + arg.put("energy", energyHandler.serializeNBT()); + arg.put("fluid", fluidHandler.writeToNBT(new CompoundTag())); // Write the progress arg.putInt("progress", this.progress); @@ -387,11 +317,6 @@ protected void saveAdditional(CompoundTag arg) { } } - @Override - public ClientboundBlockEntityDataPacket getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this, entity -> this.getUpdateTag()); - } - @Override public CompoundTag getUpdateTag() { CompoundTag compoundTag = new CompoundTag(); @@ -399,52 +324,39 @@ public CompoundTag getUpdateTag() { return compoundTag; } - @Override public void handleUpdateTag(CompoundTag tag) { load(tag); } - @Override - public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { - load(pkt.getTag()); - } - @Override public int getEnergy() { - return energy.map(IEnergyStorage::getEnergyStored).orElse(0); + return energyHandler.getEnergyStored(); } @Override public int getMaxEnergy() { - return energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); + return energyHandler.getMaxEnergyStored(); } @Override - public int getFluid() { - return tank.map(IFluidTank::getFluid).map(FluidStack::getAmount).orElse(0); + public FluidStack getFluid() { + return fluidHandler.getFluid(); } @Override public int getMaxFluid() { - return tank.map(IFluidTank::getCapacity).orElse(0); + return fluidHandler.getCapacity(); } @Override public void setEnergy(int energy) { - this.energy.ifPresent(e -> e.overrideEnergy(energy)); + energyHandler.overrideEnergy(energy); } @Override - public void setFluid(int fluid) { - this.tank.ifPresent(t -> { - var stack = new FluidStack(t.getFluid().getFluid(), fluid); - if (stack.getAmount() > t.getFluidAmount()) { - t.fill(stack, IFluidHandler.FluidAction.EXECUTE); - } else { - t.drain(t.getFluidAmount() - stack.getAmount(), IFluidHandler.FluidAction.EXECUTE); - } - }); + public void setFluid(FluidStack fluid) { + fluidHandler.setFluid(fluid); } @Override @@ -466,4 +378,14 @@ public void setProgress(int progress) { public void setMaxProgress(int maxProgress) { this.progressRequired = maxProgress; } + + @Override + public ContainerData getContainerData() { + return containerData; + } + + @Override + public void syncFluidTank() { + fluidHandler.sync(this); + } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java index 1b193ee..1b6d067 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerContainer.java @@ -1,88 +1,34 @@ package dev.ftb.ftbsba.tools.content.supercooler; import dev.ftb.ftbsba.tools.ToolsRegistry; -import dev.ftb.ftbsba.tools.content.fusion.FusingMachineContainer; -import net.minecraft.core.Vec3i; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineMenu; +import dev.ftb.ftbsba.tools.content.core.IOStackHandler; +import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.SlotItemHandler; import org.jetbrains.annotations.NotNull; -public class SuperCoolerContainer extends AbstractContainerMenu { - SuperCoolerBlockEntity entity; - ContainerData containerData; - - protected SuperCoolerContainer(int i, ContainerData containerData, Inventory arg, Player arg2, SuperCoolerBlockEntity entity) { - super(ToolsRegistry.SUPER_COOLER_CONTAINER.get(), i); - FusingMachineContainer.addPlayerSlots(arg, 8, 56, this::addSlot); - - this.entity = entity; - this.entity.ioWrapper.ifPresent(inventory -> { - int startY = 10; - addSlot(new SlotItemHandler(inventory.getInput(), 0, 42, startY)); - addSlot(new SlotItemHandler(inventory.getInput(), 1, 42, startY + 18)); - addSlot(new SlotItemHandler(inventory.getInput(), 2, 42, startY + (18 * 2))); - addSlot(new ExtractOnlySlot(inventory.getOutput(), 0, 122, startY + 19)); - }); - - this.containerData = containerData; - addDataSlots(containerData); - } - - public SuperCoolerContainer(int i, Inventory arg, FriendlyByteBuf arg2) { - this(i, arg, arg.player, (SuperCoolerBlockEntity) arg.player.level.getBlockEntity(arg2.readBlockPos())); - } - - public SuperCoolerContainer(int i, Inventory arg, Player player, SuperCoolerBlockEntity entity) { - this(i, entity.containerData, arg, player, entity); +public class SuperCoolerContainer extends AbstractMachineMenu { + public SuperCoolerContainer(int windowId, Inventory playerInventory, FriendlyByteBuf buffer) { + this(windowId, playerInventory, getTilePos(buffer)); } - @Override - public ItemStack quickMoveStack(Player arg, int index) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.slots.get(index); + public SuperCoolerContainer(int windowId, Inventory playerInventory, BlockPos pos) { + super(ToolsRegistry.SUPER_COOLER_CONTAINER.get(), windowId, playerInventory, pos); - if (slot != null && slot.hasItem()) { - ItemStack currentStack = slot.getItem(); - itemstack = currentStack.copy(); + IOStackHandler handler = blockEntity.getItemHandler(); + int startY = 10; + addSlot(new SlotItemHandler(handler.getInput(), 0, 42, startY)); + addSlot(new SlotItemHandler(handler.getInput(), 1, 42, startY + 18)); + addSlot(new SlotItemHandler(handler.getInput(), 2, 42, startY + (18 * 2))); + addSlot(new ExtractOnlySlot(handler.getOutput(), 0, 122, startY + 19)); - if (index > 35) { - if (!this.moveItemStackTo(currentStack, 0, 36, false)) { - return ItemStack.EMPTY; - } - } else if (!this.moveItemStackTo(currentStack, 36, 39, false)) { - return ItemStack.EMPTY; - } + addPlayerSlots(playerInventory, 8, 84); - if (currentStack.isEmpty()) { - slot.set(ItemStack.EMPTY); - } else { - slot.setChanged(); - } - } - - return itemstack; - } - - @Override - public boolean stillValid(Player arg) { - Vec3 position = arg.position(); - return this.entity.getBlockPos().distManhattan(new Vec3i(position.x, position.y, position.z)) <= 8; - } - - @Override - public void slotsChanged(Container arg) { - super.slotsChanged(arg); - this.entity.setChanged(); + addDataSlots(containerData); } public static class ExtractOnlySlot extends SlotItemHandler { diff --git a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java index 40a7658..73ac4b7 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java +++ b/src/main/java/dev/ftb/ftbsba/tools/content/supercooler/SuperCoolerScreen.java @@ -6,9 +6,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; -import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; import org.jetbrains.annotations.Nullable; public class SuperCoolerScreen extends FluidAndEnergyScreen { @@ -29,37 +27,31 @@ protected void renderLabels(PoseStack arg, int i, int j) { @Override public int getEnergyAmount() { - var data = this.menu.containerData; - return (data.get(0) & 0xFFFF) | (data.get(1) << 16); + return menu.blockEntity.getEnergy(); } @Override public int getEnergyCapacity() { - return this.menu.entity.energy.map(IEnergyStorage::getMaxEnergyStored).orElse(0); - } - - @Override - public int getFluidAmount() { - return this.menu.containerData.get(2); + return this.menu.blockEntity.getMaxEnergy(); } @Override public int getFluidCapacity() { - return this.menu.entity.tank.map(IFluidTank::getCapacity).orElse(0); + return this.menu.blockEntity.getMaxFluid(); } @Override public @Nullable FluidStack getFluidStack() { - return this.menu.entity.tank.map(IFluidTank::getFluid).orElse(null); + return this.menu.blockEntity.getFluid(); } @Override public int getProgress() { - return this.menu.containerData.get(3); + return menu.blockEntity.getProgress(); } @Override public int getProgressRequired() { - return this.menu.containerData.get(4); + return menu.blockEntity.getMaxProgress(); } } diff --git a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java index 53ca850..50bb19a 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java +++ b/src/main/java/dev/ftb/ftbsba/tools/integration/jei/JEIPlugin.java @@ -11,6 +11,7 @@ import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.registration.*; +import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; @@ -30,21 +31,21 @@ @JeiPlugin public class JEIPlugin implements IModPlugin { public static final ResourceLocation FTBSBTOOLS_JEI = new ResourceLocation(FTBSBA.MOD_ID, "jei"); - public static HashSet> HAMMERS = new LinkedHashSet<>() {{ - this.add(ToolsRegistry.STONE_HAMMER); - this.add(ToolsRegistry.IRON_HAMMER); - this.add(ToolsRegistry.GOLD_HAMMER); - this.add(ToolsRegistry.DIAMOND_HAMMER); - this.add(ToolsRegistry.NETHERITE_HAMMER); - this.add(ToolsRegistry.IRON_AUTO_HAMMER_BLOCK_ITEM); - this.add(ToolsRegistry.GOLD_AUTO_HAMMER_BLOCK_ITEM); - this.add(ToolsRegistry.DIAMOND_AUTO_HAMMER_BLOCK_ITEM); - this.add(ToolsRegistry.NETHERITE_AUTO_HAMMER_BLOCK_ITEM); - }}; + public static final Set> HAMMERS = Util.make(new LinkedHashSet<>(), set -> { + set.add(ToolsRegistry.STONE_HAMMER); + set.add(ToolsRegistry.IRON_HAMMER); + set.add(ToolsRegistry.GOLD_HAMMER); + set.add(ToolsRegistry.DIAMOND_HAMMER); + set.add(ToolsRegistry.NETHERITE_HAMMER); + set.add(ToolsRegistry.IRON_AUTO_HAMMER_BLOCK_ITEM); + set.add(ToolsRegistry.GOLD_AUTO_HAMMER_BLOCK_ITEM); + set.add(ToolsRegistry.DIAMOND_AUTO_HAMMER_BLOCK_ITEM); + set.add(ToolsRegistry.NETHERITE_AUTO_HAMMER_BLOCK_ITEM); + }); - public static HashSet> CROOKS = new HashSet<>() {{ - this.add(ToolsRegistry.CROOK); - }}; + public static final Set> CROOKS = Util.make(new HashSet<>(), set -> { + set.add(ToolsRegistry.CROOK); + }); @Override public ResourceLocation getPluginUid() { diff --git a/src/main/java/dev/ftb/ftbsba/tools/net/FluidTankSync.java b/src/main/java/dev/ftb/ftbsba/tools/net/FluidTankSync.java new file mode 100644 index 0000000..83b763d --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/net/FluidTankSync.java @@ -0,0 +1,38 @@ +package dev.ftb.ftbsba.tools.net; + +import dev.ftb.ftbsba.tools.ToolsClient; +import dev.ftb.ftbsba.tools.content.core.AbstractMachineBlockEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public class FluidTankSync { + private final BlockPos pos; + private final FluidStack fluidStack; + + public FluidTankSync(BlockPos pos, FluidStack fluidStack) { + this.pos = pos; + this.fluidStack = fluidStack; + } + + public FluidTankSync(FriendlyByteBuf buf) { + pos = buf.readBlockPos(); + fluidStack = buf.readFluidStack(); + } + + public void toBytes(FriendlyByteBuf buf) { + buf.writeBlockPos(pos); + buf.writeFluidStack(fluidStack); + } + + public void handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + ToolsClient.getBlockEntityAt(pos, AbstractMachineBlockEntity.class) + .ifPresent(holder -> holder.setFluid(fluidStack)); + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/net/NetworkHandler.java b/src/main/java/dev/ftb/ftbsba/tools/net/NetworkHandler.java new file mode 100644 index 0000000..fedbc4a --- /dev/null +++ b/src/main/java/dev/ftb/ftbsba/tools/net/NetworkHandler.java @@ -0,0 +1,39 @@ +package dev.ftb.ftbsba.tools.net; + +import dev.ftb.ftbsba.FTBSBA; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; + +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class NetworkHandler { + private static final String PROTOCOL_VERSION = "2"; + public static final SimpleChannel NETWORK = NetworkRegistry.ChannelBuilder + .named(new ResourceLocation(FTBSBA.MOD_ID, "main_channel")) + .clientAcceptedVersions(PROTOCOL_VERSION::equals) + .serverAcceptedVersions(PROTOCOL_VERSION::equals) + .networkProtocolVersion(() -> PROTOCOL_VERSION) + .simpleChannel(); + private static int det = 0; + + private static int nextId() { + return det++; + } + + public static void init() { + register(FluidTankSync.class, + FluidTankSync::toBytes, FluidTankSync::new, FluidTankSync::handle, + NetworkDirection.PLAY_TO_CLIENT); + } + + private static void register(Class messageType, BiConsumer encoder, Function decoder, BiConsumer> messageConsumer, NetworkDirection direction) { + NETWORK.registerMessage(nextId(), messageType, encoder, decoder, messageConsumer, Optional.ofNullable(direction)); + } +} diff --git a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java index 0cf922c..0c864fa 100644 --- a/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java +++ b/src/main/java/dev/ftb/ftbsba/tools/recipies/SuperCoolerRecipe.java @@ -18,8 +18,8 @@ public class SuperCoolerRecipe implements Recipe { private final ResourceLocation id; - public String group; - public List ingredients; + public final String group; + public final List ingredients; public EnergyComponent energyComponent; public FluidStack fluidIngredient; diff --git a/src/main/resources/assets/ftbsba/textures/block/fusing_machine_front.png b/src/main/resources/assets/ftbsba/textures/block/fusing_machine_front.png new file mode 100644 index 0000000000000000000000000000000000000000..10532fef84a7ed722aea776fe64538085ffa2e7e GIT binary patch literal 3451 zcmV->4TSQEP)StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@Kaet=&NQ1yo)fz!8$(9{E zl5I&8De@?ivaJq`iS~fQ-M#O-&%O8V<$nHUYw_LpKXNtn;w6JYAKR`IBocb@k|2@r z$Hy3-G}zz$n`&i+;mD!c+$OhkFkLKN3Oc<5Ceac}6jD^w40v^pX9BsTF*+M?`$mPb zZqVtpkpMcq10Fwn1;CB#4OXiw*|b-ytX5Yr%Q{*~&cMI+?*OC#qipf;!6xxcFrUW& z)GEsWH0)Jecf#}E|G@KHqFIPhw)m->J}8OlIHS%&fe<0J$}*>;3AM^H+pQe}5dvVE z7VgBM{q8LQzVD|I_*0k1&t6edHS&cbyWM^KK(O7~!89#Q(_&*|1J84rCke8mF#PI1 zhG9^+oX5ZMVs_-o0NOefWUm zIH^#t<2Vjecf#Gf_wc436W7hsjH8G+njtGCq+E{NqbDyGQX$VITEhL0qopgjL4>6% zsiB}`dKh?U(v0zVOhHo>+I;~e(P#h8GB^T*K5g)W3R&02+)4&S^H>;J@`Qt@^o7DqjFu3r2l42fRRvC{@ zxscVYs8_mV7+fSFU{Gi_xB2$#FPWb&7!J><+co-wG{0jRZr@s`)7`@`SMWUtO*R0~ dWP`Jj!@t>)P6*E}>7W1r002ovPDHLkV1hMhq0RsR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/block/fusing_machine_front_active.png b/src/main/resources/assets/ftbsba/textures/block/fusing_machine_front_active.png new file mode 100644 index 0000000000000000000000000000000000000000..361b8c51c1a29bc2130fa998cd1b981049fdc1ef GIT binary patch literal 3428 zcmV-q4V&_bP)StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@KaetB#{(AKq*L8@(0CTCx=AW-5ffx_xtYIJ!BA{Ga=6o=sTv}#lcMo3#09aNL zXJpg-^br8h^JE9!*x`A7o5j3AR?V@0(8luxJG*;WRuRi8vazv&>pD!51WniJfA)$048dqvBRSW_nBNy z>Gv;Kuar4CmGd2GaO>s`S_hvotra}i#?WL(hGudxu=yAJrbsOg2GPj?0000StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@Kaet&F?SeOY5R|TB6BO&cKtE*U6Ke~`K8jX$y3yTX_ zR{!M|#ngj`)E%21U1Aspb;st^Rg^z}BAFaS7lPBegOmnQ&uxZubRp1%#PdA*tO1sa z^LU;|skFk+T9s5f)g@%3(I9HXd(nmLN*IR0>)BTn3ezkV=gE#w0AL^61inw;D|8_- zO|zpx;H$71pzhc_di;b^X@%jDG<&-hq!h%oDE?)0;42Of53XIfi5^|DRGg9B6T{JC<5E92Z zL3tk9-`n%KJnI`9SbYiX<6{7{Sd8;l3oRBSruA@Tz4E+{h=H$&OPy3Y)A6}40YEZ2 zh-t>L`VyFCoby(T(aacuuke(*en_5DOx~MhduN+eIu){sOC2F(7)>+I{{DAHGh<;* zWNowD?zb#Tt8crma%HP71X`rsm9w2Xnamg;Hs5pWZZ`MKFeJClUYbppJ0n9hn=ZdE xE;u?mBspMF`L@f&MVo4^#>t6;QY!q?e*g*Y6U6fsw3Yw>002ovPDHLkV1h!iUJ?KR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/block/fusing_machine_top_active.png b/src/main/resources/assets/ftbsba/textures/block/fusing_machine_top_active.png new file mode 100644 index 0000000000000000000000000000000000000000..bbd6d83574727ed9e798f0a586fe2709586c9852 GIT binary patch literal 3378 zcmV-24bAe2P)StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@KaetCZKM>$V^RE*=D=5MZT&cN;XD$W zq%dMJGqlWuPj`6UKaNs9`xO^)(yR$dCX*#Hw^XcsEUtupyDA{v-pRp1fMeT8DNw4; z&U0O2u_!`F9A^*ZdBpzSZsjfJ7Zxy^Q`oz^0L0>Pjt&or#pA?d2~Mq7o>vz!@D)j^ zk;&%jJ~yWTNT=H{j3j1r3d2Zpba+TtuA9JDcuJi;Bu^>&uJ^IJwn`?O3E3p2h7dB0 zhLL1*^BY~c?yx2@w^XdPm?kf0UpHLk)K*OhVv$-y&UVV=a^1XLTI9mzp8P{yms~WO zs8(Grb+%Kjy8J#qW_x>!bgRkwmko}OYwVOt?Cm)yrNS@$2aN&|fSP@Z5dZ)H07*qo IM6N<$g5u3>l>h($ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/block/generic_machine_side.png b/src/main/resources/assets/ftbsba/textures/block/generic_machine_side.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf2610ea379cbef45bb89811e6452dabae7fe3d GIT binary patch literal 3308 zcmVStO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@Kaet1R5*==l1)z&Q51%sPJo$d8OziU zT2k67+DTc;!mq?%K;puUTYri>xBe88?o2l(3M@!TVIXpZdms{ZUOks9r%;}ke*LN^(=h<&IxO*qV z(eGpG^(_)#?URe?u}^DnUqZa03xF>|Qo4#SLI6}vBMbrntg^-KZVLrqty-nL^gsfP zvTv9aYoW+4&}&7-FwG1fYcQlTgz*=&}L&GpOwS3!E7hmuUqUZV!G-$rAbQlW@BH-|eIkj*W~ z9Kt}LYC48tFx75%2m=ud>tx_E5(1}d%ZXesR5hJ25cK4sR+SR)Vl+Q1s_@e+-(_`~~`s5kCUQgbgu1%>>WF&+vcHLtfr+c*rk*up>5OVa2KMEKL!OG(mnyuzP z3$M2qK_V#tuU1$2^!bZS8zwv9i!c^mByZ@-cBbm}EvBau%-@^m=;#*StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@Kaetd>W9J5=h_g-Y#QCKeD9VL&3FGPGSP!~kMtU|mI}}Wr$Q{Bo{O5EyUOK{(h$!uuRjO4g)hYl}hQWoO z&r|xchy);<6x#}Euf+gt4hGzR{f2Hj+E2Uk>o5CoR|o(;${ivXb{)P_t}%W@q0@1x z9{ZHFn|CPgf!o{L^z02T{(hSeZ#Nlc33~Mt0E&8^N6(*Ty{#5&FJJQY*)N!wsT_E{ z*=SHMm+41>T)Gt%{`uDdgS?_5sRfOm=OM{5 zx^6I6tC25g0CIcwqx7eh4(!T=HVvtP)`GHDz$SF2$y zFLUzjIr?F6U@%X(PzOUbnVdBdp+F+d5<2Y`gCt?qva)eLfB_!PJirq!ld~rEl~^r8b#gA65ejuc#gwxa}!lj5K)AxC;*J- z^8{hQ@@GqkP*5(Hv;LOg#4#AVw6HjuKXaPhWW-jZ!N-+p);G5HEe>l6-5^3leN-in fh%)1z?*i}+rJGgtWYda300000NkvXXu0mjfm-CPb literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/ftbsba/textures/block/super_cooler_front_active.png b/src/main/resources/assets/ftbsba/textures/block/super_cooler_front_active.png new file mode 100644 index 0000000000000000000000000000000000000000..fb3857218072504f19a7c4cc18439010eeeafe14 GIT binary patch literal 3409 zcmV-X4X*NuP)StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@KaetL4YJvNdU|>(*92nW2IZPSN#7-| z_ObE%2i<47$p0;{va(Fu&&^_UxW5CcKs$W+{FSlHeGc3z`-X|}c!qkn0ziIu2Pxh` zA$JJCNHRqT@L?TL{S?1+gF&^EMcX<4BAH5&Or-$mQ4}8Bxs7@`jsSjV)Zhj7s#WIx zY*K7ATWU|H?zP~eZ3A#Rbc#@=sPl66J?)}|VH8MR8({s#JK_O&aBx6rcZWx>Uh{t) zd39ewPMrlHE{l9z{^tAUa;&edab^4x-F?Xu-4C-_5{U$^V-so|IRLC`8kS`u%LVj)=jof-6A45qf)I(uD48ZgIE*YS45ibE(HH=xuA|5@0G}4-Im~7m zRb{RY4+7viHp14{HgUyY(@;9is;1E%3L!>gD5}2$BcI2B7H9zFN*Mql8WAa(CXHH+ zRZXMnd3^t}h+8RR>Ut~gjfqK&0Nwy%(U`ALv0c1c4Ivx`AU!tb`vn>Rmaa3mFi&Ry z4+IHp$Mx?Z6b{p<)fh^r(Uz7N8NY}dL_DsIp!)#O3D^}IfrhVO%oP}TEJ!1bz2y-^1svoH?C8-X?7}EVUX%T7mi}ZfTRZ!$6df^% nV%foVTq2T)?f8jHRsn#2gqbbO?`HuY00000NkvXXu0mjfk@9StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@Kaet7}ovQQy$L3ae=!i|xYKgFF}e+t-`5HejD3RFatxUeA5LWKdOLtENA14-+m z=?%!)+{L}`bI*CttG#>wq5kUiTbk9;R^#ySfS#US&MyLVwADDj2v9!FW8RLiliA?z zolZ{v7Fb_jL;IO6)mv*7Hn(>aq+E0Xs7Rlnp;M7Q0J;$Po(F&xv)J0&Bmgj*NDv!* zpa35ep8yCNx;m4#t?plpkFkqRhbYbAS1zt`~T^q-79M!rNv)I`9jxHMF%K3StgQ}DyZJTholLgx*bSs2=c6M!U zD`t_|%%BT{q;2DS64NvZ)Gj6MhQUNUPSUo~g+X>NN3?%HLAtxUSxGOW3qjJhnTW?5 zW|zxoKYs1izpSoab66LG(wWQ1$YYA7q5=W&AbYT$CG+J`GJ$z4cwMu6$RVm5u zXE8(J8$w+e_@3nS^prrbT_|C5RaGe&9)3hc`Z$h5w0{6y2=%53ibVPdRH~jbW_oH8 zfM-vi<2a7WL4H3=w10rAl#Gv$kxDJ$x&`w2eYCmx#ro0lkqS(tFG_YVr~GIpF=*(R zp)k4Z?#&T=Pu>t;O0W0 z6|f0umNqxPSht1-`J7t1wu$Cibs=cc>il13D9pFDue7YMuhH6~(RHtjlaph5d%8F{ uJmS*#Irx)j=;0t+zqc_%os^4(8=!v^TuPvNRK9Bf0000StO&>uS)ve<0AYj> z5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH15C~g000{K(ZT*WKal6< z?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj z005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5!4#~(4xGUqyucR%VFpA% z3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9;1XPc>u?taU>Kgl7`%oF z1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZqynizYLQ(?Bl0bB6giDt zK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>XmZEFX8nhlgfVQHi(M#xc zbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1#CT#lv5;6stS0Uu9wDA3 zUMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z! zkWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>Lsh-pbs)#zDT1jo7c2F-< zhp7`Zb($s3n-)XMq%EV>(3)vyY4>O^>2$gY-Gd%Qm(Z8eYv>2*=jns=cMJ`N4THx> zVkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^d=-((5|uiYR+WC0=c-gy zb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG z2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7S8PxlSDOr*I-AS3sI8l= z#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{%p4LO);n}Nd~$Sk%yw*W zyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X;pL)xc% z+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_kmoO6c3xRt`@J4dvz#WL z)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~e%5}Oeh2)X`#bu}{g3#+ z;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg6+#RN4Ot&@lW)Km@*DYM zGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnWh~P(Th`1kV8JQRPeH1Aw zGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmhY-8-3xPZ8-xPf?w_(k!T z5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C%bs^USv6UZd^m-e5|^?+ z<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3hINdvaL;7fjPeygdGYL;p zD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eTPi8AClMUo~=55LwlZVRp z zxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1`^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk9!NTH<(q(S+MDf~ceQX@ zDh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8zO#GQ^T~S@VXG71PKNocF zOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S_si{9Jg#)~P3t?+@6&(! zYQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZWdXIRo{Jz@#>IeD{>VLHU zv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl9~%uCz4Bzvli{bbrxVZ0 zepdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f&AH2?aJ@KaetR5*=glD$t;Q5eR5_XarUg4gEO z55OR;qHQq57#aLZoE+J@XyRhh&A-CU)xnKT6DI~u9SrGWKvYDOG-3g@g$e~MrMK`Y%eT)!1KZg>EQc*%RyZ!l9>da z7iKb@CUiJNd3SeT-|<+S>{1pX9g>*@I#9T-i{1F8=yn{&Mpf z*T?HOGYBb3iUi{$6RlzUKGw(2tIfBwv->72q@=oA=KT2!RH_vN0?Q9jB0d=Jq zy*NsCDcdT@BpBBd=JzLd%0#&hY0G-{VyYQGJH*TBSNk^6UaOFj4y(!kazh^P=ibpV zKR-ujhehx4UbeTlIMLtB`o<=|v}XN#fwO0ZSYG*p8w%rBb`F4k1Dj|(H;h%+_y7O^ M07*qoM6N<$g5Vc;O#lD@ literal 0 HcmV?d00001