From d0be355392950935c9e6eded8168fe2f7d6ace34 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Wed, 19 Feb 2025 23:09:01 +0100 Subject: [PATCH 01/56] =?UTF-8?q?=F0=9F=9A=B0=20Fix=20creative=20pumps=20n?= =?UTF-8?q?ot=20interacting=20with=20pipe=20networks=20properly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/mixin/FluidPropagatorMixin.java | 26 +++++++++++++++++++ src/main/resources/destroy.mixins.json | 1 + 2 files changed, 27 insertions(+) create mode 100644 src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java new file mode 100644 index 000000000..ac8f580a4 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java @@ -0,0 +1,26 @@ +package com.petrolpark.destroy.mixin; + +import com.petrolpark.destroy.block.DestroyBlocks; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.tterrag.registrate.util.entry.BlockEntry; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(FluidPropagator.class) +public class FluidPropagatorMixin +{ + @Redirect( + method="Lcom/simibubi/create/content/fluids/FluidPropagator;propagateChangedPipe(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V", + at=@At( + value="INVOKE", + target="Lcom/tterrag/registrate/util/entry/BlockEntry;has(Lnet/minecraft/world/level/block/state/BlockState;)Z", + remap=false + ), + remap=false + ) + static private boolean matchOtherPumps(BlockEntry instance, BlockState state) { + return instance.has(state) || DestroyBlocks.CREATIVE_PUMP.has(state); + } +} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 798814e0e..89a2be060 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -38,6 +38,7 @@ "FilterItemStackMixin", "FluidIngredientMixin", "FluidNetworkMixin", + "FluidPropagatorMixin", "FluidTankBlockEntityMixin", "GenericItemFillingMixin", "GhostItemMenuMixin", From 830574f796f5c25faf64b3fcd09c3e80df329a06 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 20 Feb 2025 04:33:41 +0100 Subject: [PATCH 02/56] =?UTF-8?q?=E2=9B=8F=EF=B8=8F=20Datagen=20friendly?= =?UTF-8?q?=20mineable=20tags=20(and=20other=20things)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also changed some block properties where it felt appropriate (i.e. wood sounds for plywood and aging barrels and copper sounds for inox blocks), and added the "upright on belt" tag to all bottles and cartons. --- .../create/tags/items/upright_on_belt.json | 11 +++- .../blocks/nether_crocoite_block.json | 52 +++------------- .../blocks/nether_crocoite_ore.json | 59 +++++++++++++++++++ .../forge/tags/blocks/storage_blocks.json | 1 + .../data/forge/tags/items/storage_blocks.json | 1 + .../minecraft/tags/blocks/mineable/axe.json | 3 +- .../tags/blocks/mineable/pickaxe.json | 19 ++++++ .../tags/blocks/needs_iron_tool.json | 2 + .../destroy/block/DestroyBlocks.java | 39 ++++++++++-- .../petrolpark/destroy/item/DestroyItems.java | 12 +++- .../destroy/util/DestroyTagDatagen.java | 3 +- 11 files changed, 146 insertions(+), 56 deletions(-) create mode 100644 src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_ore.json diff --git a/src/generated/resources/data/create/tags/items/upright_on_belt.json b/src/generated/resources/data/create/tags/items/upright_on_belt.json index d199aed4e..9ceb3ed22 100644 --- a/src/generated/resources/data/create/tags/items/upright_on_belt.json +++ b/src/generated/resources/data/create/tags/items/upright_on_belt.json @@ -1,9 +1,18 @@ { "values": [ + "destroy:empty_carton", + "destroy:apple_juice_carton", + "destroy:milk_carton", + "destroy:undistilled_moonshine_bottle", + "destroy:moonshine_bottle", + "destroy:chorus_wine_bottle", "destroy:unprocessed_napalm_sundae", "destroy:empty_bomb_bon", "destroy:bomb_bon", "destroy:napalm_sundae", - "#destroy:syringes" + "destroy:tear_bottle", + "destroy:urine_bottle", + "#destroy:syringes", + "#destroy:spray_bottles" ] } \ No newline at end of file diff --git a/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_block.json b/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_block.json index abe3c6b7f..1a6a14a26 100644 --- a/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_block.json +++ b/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_block.json @@ -3,53 +3,15 @@ "pools": [ { "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], "entries": [ { - "type": "minecraft:alternatives", - "children": [ - { - "type": "minecraft:item", - "conditions": [ - { - "condition": "minecraft:match_tool", - "predicate": { - "enchantments": [ - { - "enchantment": "minecraft:silk_touch", - "levels": { - "min": 1 - } - } - ] - } - } - ], - "name": "destroy:nether_crocoite_ore" - }, - { - "type": "minecraft:item", - "functions": [ - { - "add": false, - "count": { - "type": "minecraft:uniform", - "max": 5.0, - "min": 2.0 - }, - "function": "minecraft:set_count" - }, - { - "enchantment": "minecraft:fortune", - "formula": "minecraft:ore_drops", - "function": "minecraft:apply_bonus" - }, - { - "function": "minecraft:explosion_decay" - } - ], - "name": "destroy:nether_crocoite" - } - ] + "type": "minecraft:item", + "name": "destroy:nether_crocoite_block" } ], "rolls": 1.0 diff --git a/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_ore.json b/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_ore.json new file mode 100644 index 000000000..b4778c41e --- /dev/null +++ b/src/generated/resources/data/destroy/loot_tables/blocks/nether_crocoite_ore.json @@ -0,0 +1,59 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "destroy:nether_crocoite_ore" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 5.0, + "min": 2.0 + }, + "function": "minecraft:set_count" + }, + { + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops", + "function": "minecraft:apply_bonus" + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "destroy:nether_crocoite" + } + ] + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "destroy:blocks/nether_crocoite_ore" +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json index 6ed8e1296..20cf9a374 100644 --- a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json @@ -4,6 +4,7 @@ "destroy:raw_nickel_block", "destroy:chromium_block", "destroy:iodine_block", + "destroy:nether_crocoite_block", "destroy:nickel_block", "destroy:palladium_block", "destroy:platinum_block", diff --git a/src/generated/resources/data/forge/tags/items/storage_blocks.json b/src/generated/resources/data/forge/tags/items/storage_blocks.json index 4de1991f8..dc94f0ccd 100644 --- a/src/generated/resources/data/forge/tags/items/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/items/storage_blocks.json @@ -5,6 +5,7 @@ "destroy:raw_nickel_block", "destroy:chromium_block", "destroy:iodine_block", + "destroy:nether_crocoite_block", "destroy:nickel_block", "destroy:palladium_block", "destroy:platinum_block", diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json index a969b149f..57723422e 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json @@ -1,10 +1,11 @@ { "values": [ "destroy:aging_barrel", + "destroy:keypunch", "destroy:mechanical_sieve", "destroy:test_tube_rack", + "destroy:tree_tap", "destroy:vat_side", - "destroy:stainless_steel_block", "destroy:plywood", "destroy:unvarnished_plywood" ] diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index fbbff4b19..cc85900ed 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -3,22 +3,30 @@ "destroy:bubble_cap", "destroy:catalytic_converter", "destroy:centrifuge", + "destroy:colorimeter", "destroy:cooler", "destroy:creative_pump", "destroy:dynamo", "destroy:arc_furnace_lid", "destroy:element_tank", + "destroy:extrusion_die", + "destroy:keypunch", "destroy:mechanical_sieve", "destroy:pollutometer", "destroy:pumpjack", "destroy:pumpjack_cam", "destroy:pumpjack_structure", + "destroy:siphon", + "destroy:tree_tap", + "destroy:vat_controller", "destroy:vat_side", + "destroy:blacklight", "destroy:carbon_fiber_block", "destroy:fluorite_block", "destroy:raw_nickel_block", "destroy:chromium_block", "destroy:iodine_block", + "destroy:nether_crocoite_block", "destroy:nickel_block", "destroy:palladium_block", "destroy:platinum_block", @@ -37,7 +45,18 @@ "destroy:oxygen_periodic_table_block", "destroy:fluorine_periodic_table_block", "destroy:chlorine_periodic_table_block", + "destroy:chromium_periodic_table_block", + "destroy:iron_periodic_table_block", + "destroy:nickel_periodic_table_block", + "destroy:copper_periodic_table_block", + "destroy:zinc_periodic_table_block", + "destroy:rhodium_periodic_table_block", + "destroy:palladium_periodic_table_block", + "destroy:iodine_periodic_table_block", + "destroy:platinum_periodic_table_block", + "destroy:gold_periodic_table_block", "destroy:mercury_periodic_table_block", + "destroy:lead_periodic_table_block", "destroy:fiberglass_block", "destroy:borosilicate_glass", "destroy:stainless_steel_rods_block", diff --git a/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json index de359e96b..1e61f2450 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json +++ b/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json @@ -1,6 +1,8 @@ { "values": [ + "destroy:carbon_fiber_block", "destroy:fluorite_block", + "destroy:nether_crocoite_block", "destroy:platinum_block", "destroy:fluorite_ore", "destroy:deepslate_fluorite_ore", diff --git a/src/main/java/com/petrolpark/destroy/block/DestroyBlocks.java b/src/main/java/com/petrolpark/destroy/block/DestroyBlocks.java index 31d79096a..30875f9bd 100644 --- a/src/main/java/com/petrolpark/destroy/block/DestroyBlocks.java +++ b/src/main/java/com/petrolpark/destroy/block/DestroyBlocks.java @@ -2,7 +2,10 @@ import static com.petrolpark.destroy.Destroy.REGISTRATE; import static com.simibubi.create.AllTags.forgeItemTag; +import static com.simibubi.create.foundation.data.CreateRegistrate.casingConnectivity; +import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; import static com.simibubi.create.foundation.data.ModelGen.customItemModel; +import static com.simibubi.create.foundation.data.TagGen.axeOrPickaxe; import com.petrolpark.destroy.block.display.PollutometerDisplaySource; import com.petrolpark.destroy.block.entity.BubbleCapBlockEntity; @@ -78,7 +81,7 @@ public class DestroyBlocks { // BLOCK ENTITIES public static final BlockEntry AGING_BARREL = REGISTRATE.block("aging_barrel", AgingBarrelBlock::new) - .initialProperties(SharedProperties::stone) + .initialProperties(SharedProperties::wooden) .properties(p -> p .mapColor(MapColor.COLOR_BROWN) .noOcclusion() @@ -131,6 +134,7 @@ public class DestroyBlocks { public static final BlockEntry COLORIMETER = REGISTRATE.block("colorimeter", ColorimeterBlock::new) .initialProperties(() -> Blocks.OBSERVER) + .transform(TagGen.pickaxeOnly()) .onRegister(AllDisplayBehaviours.assignDataBehaviour(new ColorimeterBlockEntity.ColorimeterDisplaySource())) .item() .build() @@ -204,7 +208,8 @@ public class DestroyBlocks { .initialProperties(SharedProperties::softMetal) .properties(p -> p .noCollission() - ).item() + ).transform(TagGen.pickaxeOnly()) + .item() .transform(customItemModel()) .register(); @@ -212,7 +217,8 @@ public class DestroyBlocks { .initialProperties(SharedProperties::softMetal) .properties(p -> p .noOcclusion() - ).item(AssemblyOperatorBlockItem::new) + ).transform(TagGen.axeOrPickaxe()) + .item(AssemblyOperatorBlockItem::new) .transform(customItemModel()) .register(); @@ -300,7 +306,8 @@ public class DestroyBlocks { .initialProperties(AllBlocks.FLUID_TANK) .properties(p -> p .mapColor(MapColor.METAL) - ).item() + ).transform(TagGen.pickaxeOnly()) + .item() .build() .register(); @@ -314,6 +321,7 @@ public class DestroyBlocks { public static final BlockEntry TREE_TAP = REGISTRATE.block("tree_tap", TreeTapBlock::new) .initialProperties(AllBlocks.DEPLOYER) + .transform(TagGen.axeOrPickaxe()) .item() .build() .register(); @@ -328,6 +336,7 @@ public class DestroyBlocks { ).onRegister(AllDisplayBehaviours.assignDataBehaviour(VatControllerBlockEntity.ALL_DISPLAY_SOURCE, "vat_controller_all_contents")) .onRegister(AllDisplayBehaviours.assignDataBehaviour(VatControllerBlockEntity.SOLUTION_DISPLAY_SOURCE, "vat_controller_solution_contents")) .onRegister(AllDisplayBehaviours.assignDataBehaviour(VatControllerBlockEntity.GAS_DISPLAY_SOURCE, "vat_controller_gas_contents")) + .transform(TagGen.pickaxeOnly()) .item() .build() .register(); @@ -353,7 +362,8 @@ public class DestroyBlocks { .mapColor(MapColor.COLOR_PURPLE) .sound(SoundType.GLASS) .forceSolidOn() - ).item() + ).transform(TagGen.pickaxeOnly()) + .item() .build() .register(); @@ -429,6 +439,7 @@ public class DestroyBlocks { .properties(p -> p .strength(40f, 800f) ).transform(TagGen.pickaxeOnly()) + .tag(BlockTags.NEEDS_IRON_TOOL) .tag(DestroyBlockTags.ARC_FURNACE_TRANSFORMABLE.tag) .transform(TagGen.tagBlockAndItem("storage_blocks/carbon_fiber")) .tag(Tags.Items.STORAGE_BLOCKS) @@ -586,7 +597,10 @@ public class DestroyBlocks { .instrument(NoteBlockInstrument.IRON_XYLOPHONE) .strength(7f, 8f) ).transform(TagGen.pickaxeOnly()) - .transform(BuilderTransformers.casing(() -> DestroySpriteShifts.STAINLESS_STEEL_BLOCK)) + .properties(p -> p.sound(SoundType.COPPER)) + .blockstate((c, p) -> p.simpleBlock(c.get())) + .onRegister(connectedTextures(() -> new EncasedCTBehaviour(DestroySpriteShifts.STAINLESS_STEEL_BLOCK))) + .onRegister(casingConnectivity((block, cc) -> cc.makeCasing(block, DestroySpriteShifts.STAINLESS_STEEL_BLOCK))) .tag(BlockTags.NEEDS_STONE_TOOL) .tag(Tags.Blocks.STORAGE_BLOCKS) .tag(BlockTags.BEACON_BASE_BLOCKS) @@ -861,6 +875,7 @@ public class DestroyBlocks { CHROMIUM_PERIODIC_TABLE_BLOCK = REGISTRATE.block("chromium_periodic_table_block", PeriodicTableBlock::new) .initialProperties(CHROMIUM_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/chromium")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/chromium")) @@ -869,6 +884,7 @@ public class DestroyBlocks { IRON_PERIODIC_TABLE_BLOCK = REGISTRATE.block("iron_periodic_table_block", PeriodicTableBlock::new) .initialProperties(() -> Blocks.IRON_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, Tags.Blocks.STORAGE_BLOCKS_IRON) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, Tags.Items.STORAGE_BLOCKS_IRON) @@ -877,6 +893,7 @@ public class DestroyBlocks { NICKEL_PERIODIC_TABLE_BLOCK = REGISTRATE.block("nickel_periodic_table_block", PeriodicTableBlock::new) .initialProperties(NICKEL_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/nickel")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/nickel")) @@ -885,6 +902,7 @@ public class DestroyBlocks { COPPER_PERIODIC_TABLE_BLOCK = REGISTRATE.block("copper_periodic_table_block", PeriodicTableBlock::new) .initialProperties(() -> Blocks.COPPER_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, Tags.Blocks.STORAGE_BLOCKS_COPPER) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, Tags.Items.STORAGE_BLOCKS_COPPER) @@ -893,6 +911,7 @@ public class DestroyBlocks { ZINC_PERIODIC_TABLE_BLOCK = REGISTRATE.block("zinc_periodic_table_block", PeriodicTableBlock::new) .initialProperties(AllBlocks.ZINC_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/zinc")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/zinc")) @@ -901,6 +920,7 @@ public class DestroyBlocks { RHODIUM_PERIODIC_TABLE_BLOCK = REGISTRATE.block("rhodium_periodic_table_block", PeriodicTableBlock::new) .initialProperties(RHODIUM_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/rhodium")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/rhodium")) @@ -909,6 +929,7 @@ public class DestroyBlocks { PALLADIUM_PERIODIC_TABLE_BLOCK = REGISTRATE.block("palladium_periodic_table_block", PeriodicTableBlock::new) .initialProperties(PALLADIUM_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/palladium")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/palladium")) @@ -917,6 +938,7 @@ public class DestroyBlocks { IODINE_PERIODIC_TABLE_BLOCK = REGISTRATE.block("iodine_periodic_table_block", PeriodicTableBlock::new) .initialProperties(IODINE_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/iodine")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/iodine")) @@ -925,6 +947,7 @@ public class DestroyBlocks { PLATINUM_PERIODIC_TABLE_BLOCK = REGISTRATE.block("platinum_periodic_table_block", PeriodicTableBlock::new) .initialProperties(CHROMIUM_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/platinum")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/platinum")) @@ -933,6 +956,7 @@ public class DestroyBlocks { GOLD_PERIODIC_TABLE_BLOCK = REGISTRATE.block("gold_periodic_table_block", PeriodicTableBlock::new) .initialProperties(() -> Blocks.GOLD_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, Tags.Blocks.STORAGE_BLOCKS_GOLD) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, Tags.Items.STORAGE_BLOCKS_GOLD) @@ -952,6 +976,7 @@ public class DestroyBlocks { LEAD_PERIODIC_TABLE_BLOCK = REGISTRATE.block("lead_periodic_table_block", PeriodicTableBlock::new) .initialProperties(CHROMIUM_BLOCK) + .transform(TagGen.pickaxeOnly()) .tag(Tags.Blocks.STORAGE_BLOCKS, AllTags.forgeBlockTag("storage_blocks/lead")) .item(PeriodicTableBlockItem::new) .tag(Tags.Items.STORAGE_BLOCKS, forgeItemTag("storage_blocks/lead")) @@ -1014,6 +1039,7 @@ public class DestroyBlocks { PLYWOOD = REGISTRATE.block("plywood", FlippableRotatedPillarBlock::new) .properties(p -> p .mapColor(MapColor.WOOD) + .sound(SoundType.WOOD) .instrument(NoteBlockInstrument.BASS) .strength(4.0f, 6.0f) ).tag(BlockTags.MINEABLE_WITH_AXE, BlockTags.PLANKS) @@ -1025,6 +1051,7 @@ public class DestroyBlocks { UNVARNISHED_PLYWOOD = REGISTRATE.block("unvarnished_plywood", FlippableRotatedPillarBlock::new) .properties(p -> p .mapColor(MapColor.WOOD) + .sound(SoundType.WOOD) .instrument(NoteBlockInstrument.BASS) .strength(3.0f, 5.0f) .ignitedByLava() diff --git a/src/main/java/com/petrolpark/destroy/item/DestroyItems.java b/src/main/java/com/petrolpark/destroy/item/DestroyItems.java index 7651ae416..6b258b57f 100644 --- a/src/main/java/com/petrolpark/destroy/item/DestroyItems.java +++ b/src/main/java/com/petrolpark/destroy/item/DestroyItems.java @@ -458,6 +458,7 @@ public class DestroyItems { .food(DestroyFoods.MASHED_POTATO) ).register(), EMPTY_CARTON = REGISTRATE.item("empty_carton", Item::new) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(); public static final ItemEntry @@ -480,7 +481,8 @@ public class DestroyItems { .properties(p -> p .food(DestroyFoods.APPLE_JUICE) .craftRemainder(EMPTY_CARTON.get()) - ).register(); + ).tag(AllItemTags.UPRIGHT_ON_BELT.tag) + .register(); public static final ItemEntry @@ -488,7 +490,8 @@ public class DestroyItems { .properties(p -> p .food(DestroyFoods.MILK_CARTON) .craftRemainder(EMPTY_CARTON.get()) - ).register(); + ).tag(AllItemTags.UPRIGHT_ON_BELT.tag) + .register(); public static final ItemEntry @@ -498,6 +501,7 @@ public class DestroyItems { .craftRemainder(Items.GLASS_BOTTLE) .stacksTo(16) ).tag(DestroyItemTags.ALCOHOLIC_DRINKS.tag) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(), MOONSHINE_BOTTLE = REGISTRATE.item("moonshine_bottle", p -> new AlcoholicDrinkItem(p, 3)) .properties(p -> p @@ -505,6 +509,7 @@ public class DestroyItems { .craftRemainder(Items.GLASS_BOTTLE) .stacksTo(16) ).tag(DestroyItemTags.ALCOHOLIC_DRINKS.tag) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(); public static final ItemEntry @@ -515,6 +520,7 @@ public class DestroyItems { .craftRemainder(Items.GLASS_BOTTLE) .stacksTo(16) ).tag(DestroyItemTags.ALCOHOLIC_DRINKS.tag) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(); // SEQUENCED ASSEMBLY INTERMEDIATES @@ -710,8 +716,10 @@ public class DestroyItems { MESH = REGISTRATE.item("mesh", Item::new) .register(), TEAR_BOTTLE = REGISTRATE.item("tear_bottle", Item::new) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(), URINE_BOTTLE = REGISTRATE.item("urine_bottle", Item::new) + .tag(AllItemTags.UPRIGHT_ON_BELT.tag) .register(), VOLTAIC_PILE = REGISTRATE.item("voltaic_pile", Item::new) .tag(DestroyItemTags.LIABLE_TO_CHANGE.tag) diff --git a/src/main/java/com/petrolpark/destroy/util/DestroyTagDatagen.java b/src/main/java/com/petrolpark/destroy/util/DestroyTagDatagen.java index 7227fbe62..e3322616b 100644 --- a/src/main/java/com/petrolpark/destroy/util/DestroyTagDatagen.java +++ b/src/main/java/com/petrolpark/destroy/util/DestroyTagDatagen.java @@ -32,7 +32,8 @@ private static void genItemTags(RegistrateTagsProvider provIn) { // Create Tags prov.tag(AllItemTags.UPRIGHT_ON_BELT.tag) - .addTag(DestroyItemTags.SYRINGES.tag); + .addTag(DestroyItemTags.SYRINGES.tag) + .addTag(DestroyItemTags.SPRAY_BOTTLES.tag); // Curios Tags prov.tag(TagKey.create(Registries.ITEM, CompatMods.CURIOS.asResource("head"))) From 16baea2cf6c8c55a3be8d02ee845c76bf840c87b Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 20 Feb 2025 04:41:02 +0100 Subject: [PATCH 03/56] =?UTF-8?q?=F0=9F=94=A7More=20wrenchability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allowing blocks to be picked up with a wrench via the IWrenchable interface instead of going through a tag feels more consistent with how Create does it with its own blocks. This also allows some blocks to be rotated with the wrench, i.e. the Catalytic Converter and the Pollutometer. --- .../destroy/block/CatalyticConverterBlock.java | 3 ++- .../java/com/petrolpark/destroy/block/CoolerBlock.java | 3 ++- .../petrolpark/destroy/block/PollutometerBlock.java | 3 ++- .../com/petrolpark/destroy/block/PumpjackBlock.java | 10 +++++++++- .../java/com/petrolpark/destroy/block/SiphonBlock.java | 10 +++++++++- .../petrolpark/destroy/block/VatControllerBlock.java | 9 ++++++++- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/CatalyticConverterBlock.java b/src/main/java/com/petrolpark/destroy/block/CatalyticConverterBlock.java index 903d8fa8e..9750c4922 100644 --- a/src/main/java/com/petrolpark/destroy/block/CatalyticConverterBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/CatalyticConverterBlock.java @@ -3,6 +3,7 @@ import com.petrolpark.destroy.block.entity.CatalyticConverterBlockEntity; import com.petrolpark.destroy.block.entity.DestroyBlockEntityTypes; import com.petrolpark.destroy.block.shape.DestroyShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; @@ -17,7 +18,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class CatalyticConverterBlock extends DirectionalBlock implements IBE { +public class CatalyticConverterBlock extends DirectionalBlock implements IBE, IWrenchable { protected CatalyticConverterBlock(Properties properties) { super(properties); diff --git a/src/main/java/com/petrolpark/destroy/block/CoolerBlock.java b/src/main/java/com/petrolpark/destroy/block/CoolerBlock.java index dfc9b2e27..025c65c28 100644 --- a/src/main/java/com/petrolpark/destroy/block/CoolerBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/CoolerBlock.java @@ -7,6 +7,7 @@ import com.petrolpark.destroy.block.shape.DestroyShapes; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.processing.basin.BasinBlockEntity; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; @@ -32,7 +33,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class CoolerBlock extends Block implements IBE { +public class CoolerBlock extends Block implements IBE, IWrenchable { public static final EnumProperty COLD_LEVEL = EnumProperty.create("breeze", ColdnessLevel.class); diff --git a/src/main/java/com/petrolpark/destroy/block/PollutometerBlock.java b/src/main/java/com/petrolpark/destroy/block/PollutometerBlock.java index eb75d364d..fee859229 100644 --- a/src/main/java/com/petrolpark/destroy/block/PollutometerBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/PollutometerBlock.java @@ -3,6 +3,7 @@ import com.petrolpark.destroy.block.entity.DestroyBlockEntityTypes; import com.petrolpark.destroy.block.entity.PollutometerBlockEntity; import com.petrolpark.destroy.block.shape.DestroyShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; @@ -17,7 +18,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class PollutometerBlock extends Block implements IBE { +public class PollutometerBlock extends Block implements IBE, IWrenchable { public static final DirectionProperty DIRECTION = BlockStateProperties.HORIZONTAL_FACING; diff --git a/src/main/java/com/petrolpark/destroy/block/PumpjackBlock.java b/src/main/java/com/petrolpark/destroy/block/PumpjackBlock.java index f12e3f845..9d6910e00 100644 --- a/src/main/java/com/petrolpark/destroy/block/PumpjackBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/PumpjackBlock.java @@ -9,6 +9,7 @@ import com.petrolpark.destroy.block.entity.DestroyBlockEntityTypes; import com.petrolpark.destroy.block.entity.PumpjackBlockEntity; import com.petrolpark.destroy.block.shape.DestroyShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.block.IBE; @@ -17,7 +18,9 @@ import net.minecraft.core.Direction.Axis; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -30,13 +33,18 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class PumpjackBlock extends HorizontalDirectionalBlock implements IBE { +public class PumpjackBlock extends HorizontalDirectionalBlock implements IBE, IWrenchable { public PumpjackBlock(Properties properties) { super(properties); registerDefaultState(defaultBlockState().setValue(FACING, Direction.NORTH)); }; + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.FAIL; + } + @Override protected void createBlockStateDefinition(Builder builder) { super.createBlockStateDefinition(builder); diff --git a/src/main/java/com/petrolpark/destroy/block/SiphonBlock.java b/src/main/java/com/petrolpark/destroy/block/SiphonBlock.java index 9d4b00705..86877efa6 100644 --- a/src/main/java/com/petrolpark/destroy/block/SiphonBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/SiphonBlock.java @@ -2,12 +2,15 @@ import com.petrolpark.destroy.block.entity.DestroyBlockEntityTypes; import com.petrolpark.destroy.block.entity.SiphonBlockEntity; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -15,12 +18,17 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -public class SiphonBlock extends Block implements IBE { +public class SiphonBlock extends Block implements IBE, IWrenchable { public SiphonBlock(Properties properties) { super(properties); }; + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.FAIL; + } + @Override protected void createBlockStateDefinition(Builder builder) { builder.add(BlockStateProperties.POWERED); diff --git a/src/main/java/com/petrolpark/destroy/block/VatControllerBlock.java b/src/main/java/com/petrolpark/destroy/block/VatControllerBlock.java index 07bfee023..0947e008a 100644 --- a/src/main/java/com/petrolpark/destroy/block/VatControllerBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/VatControllerBlock.java @@ -8,6 +8,7 @@ import com.petrolpark.destroy.client.gui.screen.VatScreen; import com.petrolpark.destroy.item.IMixtureStorageItem; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.gui.ScreenOpener; @@ -22,6 +23,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.HorizontalDirectionalBlock; @@ -34,13 +36,18 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.DistExecutor; -public class VatControllerBlock extends HorizontalDirectionalBlock implements IBE, ISpecialMixtureContainerBlock { +public class VatControllerBlock extends HorizontalDirectionalBlock implements IBE, ISpecialMixtureContainerBlock, IWrenchable { public VatControllerBlock(Properties properties) { super(properties); registerDefaultState(defaultBlockState().setValue(FACING, Direction.NORTH)); }; + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.FAIL; + } + @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext context) { From 8b533707d1cdb82bf5f7feed9e8ec40db19da403 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 20 Feb 2025 04:44:59 +0100 Subject: [PATCH 04/56] =?UTF-8?q?=E2=9A=A1Fixed=20a=20couple=20wrench=20re?= =?UTF-8?q?lated=20issues=20with=20the=20Dynamo=20when=20in=20arc=20furnac?= =?UTF-8?q?e=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the lid of the arc furnace turning into a second dynamo when the actual dynamo is right clicked with a wrench instead of rotating as intended. The dynamo also didn't revert back to its normal form when the lid is removed, so I've added an extra check to address that. --- .../petrolpark/destroy/block/DynamoBlock.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/DynamoBlock.java b/src/main/java/com/petrolpark/destroy/block/DynamoBlock.java index 675c72911..aa26bbf82 100644 --- a/src/main/java/com/petrolpark/destroy/block/DynamoBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/DynamoBlock.java @@ -23,6 +23,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition.Builder; @@ -31,6 +32,7 @@ import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.common.util.Lazy; public class DynamoBlock extends KineticBlock implements IBE { @@ -101,18 +103,32 @@ public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, Co @Override public InteractionResult onWrenched(BlockState state, UseOnContext context) { - if (context.getLevel().getBlockState(context.getClickedPos().below()).getBlock() instanceof ArcFurnaceLidBlock) context.getLevel().setBlock(context.getClickedPos().below(), state.cycle(ArcFurnaceLidBlock.AXIS), 3); - context.getLevel().setBlock(context.getClickedPos(), state.cycle(AXIS), 3); + Level level = context.getLevel(); + BlockState stateBelow = level.getBlockState(context.getClickedPos().below()); + if (stateBelow.getBlock() instanceof ArcFurnaceLidBlock) level.setBlock(context.getClickedPos().below(), stateBelow.cycle(ArcFurnaceLidBlock.AXIS), 3); + level.setBlock(context.getClickedPos(), state.cycle(AXIS), 3); + + if (level.getBlockState(context.getClickedPos()) != state) + playRotateSound(context.getLevel(), context.getClickedPos()); + return InteractionResult.SUCCESS; }; public void checkForArcFurnace(Level level, BlockPos pos, BlockState state) { BlockState stateBelow = level.getBlockState(pos.below()); - if (state.getValue(ARC_FURNACE)) return; - if (stateBelow.is(DestroyBlocks.CARBON_FIBER_BLOCK.get()) || level.getBlockState(pos.below()).getBlock() instanceof ArcFurnaceLidBlock) { - level.getBlockEntity(pos, DestroyBlockEntityTypes.DYNAMO.get()).ifPresent(dynamo -> dynamo.arcFurnaceBlock = () -> stateBelow); - level.setBlock(pos.below(), DestroyBlocks.ARC_FURNACE_LID.getDefaultState().setValue(ArcFurnaceLidBlock.AXIS, state.getValue(AXIS)), 3); - level.setBlock(pos, state.setValue(ARC_FURNACE, true), 3); + boolean belowIsArcFurnaceLidBlock = stateBelow.is(DestroyBlocks.CARBON_FIBER_BLOCK.get()) || level.getBlockState(pos.below()).getBlock() instanceof ArcFurnaceLidBlock; + + if (state.getValue(ARC_FURNACE)) { + if (!belowIsArcFurnaceLidBlock) { + level.getBlockEntity(pos, DestroyBlockEntityTypes.DYNAMO.get()).ifPresent(dynamo -> dynamo.arcFurnaceBlock = Lazy.of(Blocks.AIR::defaultBlockState)); + level.setBlock(pos, state.setValue(ARC_FURNACE, false), 3); + }; + } else { + if (belowIsArcFurnaceLidBlock) { + level.getBlockEntity(pos, DestroyBlockEntityTypes.DYNAMO.get()).ifPresent(dynamo -> dynamo.arcFurnaceBlock = () -> stateBelow); + level.setBlock(pos.below(), DestroyBlocks.ARC_FURNACE_LID.getDefaultState().setValue(ArcFurnaceLidBlock.AXIS, state.getValue(AXIS)), 3); + level.setBlock(pos, state.setValue(ARC_FURNACE, true), 3); + }; }; }; From 6918cfe39d7b4bfec02864fecfc6d51ddd22f771 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 20 Feb 2025 04:47:00 +0100 Subject: [PATCH 05/56] =?UTF-8?q?=F0=9F=94=91Allow=20keypunch=20to=20be=20?= =?UTF-8?q?rotated=20when=20right=20clicked=20with=20a=20wrench=20instead?= =?UTF-8?q?=20of=20opening=20its=20GUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A little thing I noticed when testing the wrenchability of every block. Feels like it makes more sense that way. --- src/main/java/com/petrolpark/destroy/block/KeypunchBlock.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/petrolpark/destroy/block/KeypunchBlock.java b/src/main/java/com/petrolpark/destroy/block/KeypunchBlock.java index 7c616cd3a..81c3f175c 100644 --- a/src/main/java/com/petrolpark/destroy/block/KeypunchBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/KeypunchBlock.java @@ -5,6 +5,7 @@ import com.petrolpark.destroy.block.entity.DestroyBlockEntityTypes; import com.petrolpark.destroy.block.entity.KeypunchBlockEntity; import com.petrolpark.destroy.client.gui.menu.KeypunchScreen; +import com.simibubi.create.AllItems; import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.IBE; @@ -52,6 +53,8 @@ public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntit @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + if (AllItems.WRENCH.isIn(player.getItemInHand(hand))) return InteractionResult.PASS; + return onBlockEntityUse(level, pos, be -> { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> displayScreen(be, player)); return InteractionResult.SUCCESS; From 81011040f0c41ffd36d25b810302146852e9293d Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 20 Feb 2025 04:49:15 +0100 Subject: [PATCH 06/56] =?UTF-8?q?=F0=9F=A7=AAFixed=20test=20tube=20racks?= =?UTF-8?q?=20not=20dropping=20their=20contents=20when=20broken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit super.destroy deletes the block entity, so the second line never gets to do what it's supposed to do. I've also moved the logic to onRemove, since this is what Create seems to use for its own blocks with inventories. --- .../com/petrolpark/destroy/block/TestTubeRackBlock.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/TestTubeRackBlock.java b/src/main/java/com/petrolpark/destroy/block/TestTubeRackBlock.java index 4916bb117..bc28aa145 100644 --- a/src/main/java/com/petrolpark/destroy/block/TestTubeRackBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/TestTubeRackBlock.java @@ -84,10 +84,10 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player }; @Override - public void destroy(LevelAccessor pLevel, BlockPos pPos, BlockState pState) { - super.destroy(pLevel, pPos, pState); - withBlockEntityDo(pLevel, pPos, be -> ItemHelper.dropContents(be.getLevel(), pPos, be.inv)); - }; + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { + withBlockEntityDo(world, pos, be -> ItemHelper.dropContents(be.getLevel(), pos, be.inv)); + super.onRemove(state, world, pos, newState, isMoving); + } /** * @param state From 75e6b9510c492e3417fe564b56551ead87894208 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 22 Feb 2025 00:38:04 +0100 Subject: [PATCH 07/56] =?UTF-8?q?=F0=9F=91=8B=20Fix=20broken=20right=20cli?= =?UTF-8?q?ck=20interaction=20with=20Create's=20configurable=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/client/gui/screen/BetterValueSettingsScreen.java | 2 +- .../com/petrolpark/destroy/mixin/ValueSettingsPacketMixin.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/client/gui/screen/BetterValueSettingsScreen.java b/src/main/java/com/petrolpark/destroy/client/gui/screen/BetterValueSettingsScreen.java index fcfabb3df..e4fab1c5c 100644 --- a/src/main/java/com/petrolpark/destroy/client/gui/screen/BetterValueSettingsScreen.java +++ b/src/main/java/com/petrolpark/destroy/client/gui/screen/BetterValueSettingsScreen.java @@ -38,7 +38,7 @@ public BetterValueSettingsScreen(BlockPos pos, Direction sideAccessed, Interacti protected void saveAndClose(double mouseX, double mouseY) { ValueSettings closest = getClosestCoordinate((int) mouseX, (int) mouseY); AllPackets.getChannel() - .sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), hand, sideAccessed, + .sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), null, sideAccessed, AllKeys.ctrlDown())); onClose(); }; diff --git a/src/main/java/com/petrolpark/destroy/mixin/ValueSettingsPacketMixin.java b/src/main/java/com/petrolpark/destroy/mixin/ValueSettingsPacketMixin.java index fa1284289..3f14cbe25 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/ValueSettingsPacketMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/ValueSettingsPacketMixin.java @@ -33,6 +33,7 @@ protected void applySettings(ServerPlayer player, SmartBlockEntity be) { continue; if (hand != null) { valueSettingsBehaviour.onShortInteract(player, hand, side); + return; }; if (valueSettingsBehaviour instanceof SmartValueSettingsBehaviour smartValueSettingsBehaviour) { smartValueSettingsBehaviour.acceptAccessInformation(hand, side); From 661c62684b4a394901e4a106ca9c8eba065b784b Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 22 Feb 2025 21:34:15 +0100 Subject: [PATCH 08/56] =?UTF-8?q?=F0=9F=92=A7=20Fix=20vat=20fluid=20dupe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes pumping mixtures into a vat causing one extra tick worth of fluid to come into existence --- .../com/petrolpark/destroy/block/entity/VatSideBlockEntity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java b/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java index ce8543cbd..bb99a1d9b 100644 --- a/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java @@ -118,7 +118,6 @@ protected AABB createRenderBoundingBox() { @Override public void addBehaviours(List behaviours) { inputBehaviour = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.TYPE, this, 1, BUFFER_TANK_CAPACITY, false) - .whenFluidUpdates(this::tryInsertFluidInVat) .forbidExtraction(); behaviours.add(inputBehaviour); //fluidCapability = LazyOptional.empty(); // Temporarily set this to an empty optional From 02fde74c94e4297424efd83254a4d195180c988e Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Feb 2025 05:54:39 +0100 Subject: [PATCH 09/56] =?UTF-8?q?=F0=9F=8C=A1=EF=B8=8F=20Fix=20vat=20tempe?= =?UTF-8?q?rature=20and=20pressure=20monitors=20not=20saving=20their=20thr?= =?UTF-8?q?esholds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behaviour/RedstoneQuantityMonitorBehaviour.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/entity/behaviour/RedstoneQuantityMonitorBehaviour.java b/src/main/java/com/petrolpark/destroy/block/entity/behaviour/RedstoneQuantityMonitorBehaviour.java index 013174a6e..b2f05c3ce 100644 --- a/src/main/java/com/petrolpark/destroy/block/entity/behaviour/RedstoneQuantityMonitorBehaviour.java +++ b/src/main/java/com/petrolpark/destroy/block/entity/behaviour/RedstoneQuantityMonitorBehaviour.java @@ -72,11 +72,9 @@ public void tick() { @Override public void read(CompoundTag nbt, boolean clientPacket) { super.read(nbt, clientPacket); - if (quantityObserved.isPresent()) { - oldStrength = nbt.getInt("OldRedstoneStrength"); - lowerThreshold = nbt.getFloat("LowerObservedQuantityThreshold"); - upperThreshold = nbt.getFloat("UpperObservedQuantityThreshold"); - }; + oldStrength = nbt.getInt("OldRedstoneStrength"); + lowerThreshold = nbt.getFloat("LowerObservedQuantityThreshold"); + upperThreshold = nbt.getFloat("UpperObservedQuantityThreshold"); }; @Override From 497566f81cd4784081b093e5e2b78091f4a0cb18 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Feb 2025 18:11:40 +0100 Subject: [PATCH 10/56] =?UTF-8?q?=F0=9F=93=A1=20Fix=20temperature/pressure?= =?UTF-8?q?=20sensors=20not=20saving=20their=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/petrolpark/destroy/block/VatSideBlock.java | 8 +++++--- .../destroy/block/entity/VatSideBlockEntity.java | 7 +++++++ .../gui/screen/AbstractQuantityObservingScreen.java | 8 ++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/VatSideBlock.java b/src/main/java/com/petrolpark/destroy/block/VatSideBlock.java index e43e52851..f5865d6c6 100644 --- a/src/main/java/com/petrolpark/destroy/block/VatSideBlock.java +++ b/src/main/java/com/petrolpark/destroy/block/VatSideBlock.java @@ -20,6 +20,7 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntityTicker; import com.simibubi.create.foundation.gui.ScreenOpener; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; @@ -73,7 +74,7 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player return onBlockEntityUse(level, pos, be -> { if (!(be instanceof VatSideBlockEntity vbe)) return InteractionResult.PASS; if (vbe.getDisplayType().quantityObserved.isPresent()) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(vbe)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(vbe, player)); return InteractionResult.SUCCESS; }; return InteractionResult.PASS; @@ -81,8 +82,9 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player }; @OnlyIn(Dist.CLIENT) - public void openScreen(VatSideBlockEntity vbe) { - ScreenOpener.open(new RedstoneMonitorVatSideScreen(vbe)); + public void openScreen(VatSideBlockEntity vbe, Player player) { + if (player instanceof LocalPlayer) + ScreenOpener.open(new RedstoneMonitorVatSideScreen(vbe)); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java b/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java index bb99a1d9b..0b003053f 100644 --- a/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/block/entity/VatSideBlockEntity.java @@ -242,6 +242,13 @@ protected void read(CompoundTag tag, boolean clientPacket) { spoutingFluid = FluidStack.loadFluidStackFromNBT(tag.getCompound("SpoutingFluid")); ventOpenness.chase(displayType == DisplayType.OPEN_VENT ? 1f : 0f, 0.3f, Chaser.EXP); }; + + if(!redstoneMonitor.quantityObserved.isPresent() && getDisplayType().quantityObserved.isPresent()) { + redstoneMonitor.quantityObserved = getDisplayType().quantityObserved.map(f -> () -> { + VatControllerBlockEntity vc = getController(); + return vc == null ? 0.f : f.apply(vc); + }); + } redstoneMonitor.withLabel(getDisplayType().quantityLabel); }; diff --git a/src/main/java/com/petrolpark/destroy/client/gui/screen/AbstractQuantityObservingScreen.java b/src/main/java/com/petrolpark/destroy/client/gui/screen/AbstractQuantityObservingScreen.java index 223bd0a64..08ab76623 100644 --- a/src/main/java/com/petrolpark/destroy/client/gui/screen/AbstractQuantityObservingScreen.java +++ b/src/main/java/com/petrolpark/destroy/client/gui/screen/AbstractQuantityObservingScreen.java @@ -94,6 +94,14 @@ public void tick() { }; }; + @Override + public void onClose() { + lowerBound.setFocused(false); + upperBound.setFocused(false); + tick(); + super.onClose(); + } + @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (getFocused() instanceof EditBox && (keyCode == InputConstants.KEY_RETURN || keyCode == InputConstants.KEY_NUMPADENTER)) for (EditBox box : List.of(lowerBound, upperBound)) { From eae9abc423ed812df98442d4b39db26ad34f5e27 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Feb 2025 18:12:44 +0100 Subject: [PATCH 11/56] =?UTF-8?q?=F0=9F=92=A7=20Cleaned=20up=20creative=20?= =?UTF-8?q?pump=20GUI=20to=20be=20slightly=20more=20compact?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/entity/CreativePumpBlockEntity.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/entity/CreativePumpBlockEntity.java b/src/main/java/com/petrolpark/destroy/block/entity/CreativePumpBlockEntity.java index 0a4ea2682..538a4e6ce 100644 --- a/src/main/java/com/petrolpark/destroy/block/entity/CreativePumpBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/block/entity/CreativePumpBlockEntity.java @@ -10,13 +10,17 @@ import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.infrastructure.config.AllConfigs; +import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -38,15 +42,20 @@ public void addBehaviours(List behaviours) { pumpSpeedBehaviour = new ScrollValueBehaviour(Component.translatable("block.destroy.creative_pump.speed"), this, new CreativePumpValueSlot()) { @Override public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { - return new ValueSettingsBoard(label, max, 16, ImmutableList.of(Component.translatable("block.destroy.creative_pump.speed")), new ValueSettingsFormatter(ValueSettings::format)); + return new ValueSettingsBoard(label, max, 16, ImmutableList.of(Components.literal("\u2192").withStyle(ChatFormatting.BOLD)), new ValueSettingsFormatter(this::formatSettings)); + }; + + public MutableComponent formatSettings(ValueSettings settings) { + return Lang.number(Math.max(1, settings.value())).component(); }; } - .between(0, AllConfigs.server().kinetics.maxRotationSpeed.get()) + .between(1, AllConfigs.server().kinetics.maxRotationSpeed.get()) .withCallback(i -> { simulatedSpeed = i; - updatePressureChange(); + if (level != null && !level.isClientSide) + updatePressureChange(); }); - pumpSpeedBehaviour.setValue(simulatedSpeed); + pumpSpeedBehaviour.setValue(16); behaviours.add(pumpSpeedBehaviour); }; From c408da4e1030d9ee3cca8acd84829e603d3c634a Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Feb 2025 18:14:07 +0100 Subject: [PATCH 12/56] =?UTF-8?q?=F0=9F=94=AA=20Fully=20clientside=20Swiss?= =?UTF-8?q?=20Army=20Knife=20animation=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/item/SwissArmyKnifeItem.java | 91 ++++++++++--------- .../item/renderer/SwissArmyKnifeRenderer.java | 21 ++++- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/item/SwissArmyKnifeItem.java b/src/main/java/com/petrolpark/destroy/item/SwissArmyKnifeItem.java index e4d28ac20..4f19556b7 100644 --- a/src/main/java/com/petrolpark/destroy/item/SwissArmyKnifeItem.java +++ b/src/main/java/com/petrolpark/destroy/item/SwissArmyKnifeItem.java @@ -1,13 +1,12 @@ package com.petrolpark.destroy.item; -import java.util.EnumMap; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Consumer; import java.util.function.Supplier; import javax.annotation.Nullable; +import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.block.IBlockWithPreferredSwissArmyKnifeTool; import com.petrolpark.destroy.entity.IEntityWithPreferredSwissArmyKnifeTool; import com.petrolpark.destroy.item.renderer.SwissArmyKnifeRenderer; @@ -56,20 +55,50 @@ public class SwissArmyKnifeItem extends DiggerItem { private static int timeUntilToolPutAway = 20; - @Nullable - public static Tool selectedTool = null; - public SwissArmyKnifeItem(float attackDamageModifier, float attackSpeedModifier, Tier tier, Properties properties) { super(attackDamageModifier, attackSpeedModifier, tier, BlockTags.MINEABLE_WITH_PICKAXE, properties); // The tag supplied here is ignored }; + @OnlyIn(Dist.CLIENT) + public static class ClientState { + @Nullable + public Tool selectedTool = null; + public Tool lastSelectedTool = null; + public int animTimer = 0; + + public Map chasers; + + public ClientState() { + chasers = new EnumMap<>(Tool.class); + for (Tool tool : Tool.values()) { + chasers.put(tool, LerpedFloat.angular().chase(0d, 0.4d, Chaser.EXP)); + }; + }; + + public void tick() { + chasers.values().forEach(chaser -> chaser.tickChaser()); + + if(selectedTool != lastSelectedTool) { + animTimer++; + if(animTimer >= 8) { + animTimer = 0; + lastSelectedTool = selectedTool; + chasers.forEach((entry, value) -> value.chase(entry == selectedTool ? 1d : 0d, 0.4d, Chaser.EXP)); + }; + }; + }; + }; + + @OnlyIn(Dist.CLIENT) + private static Map clientStates = new WeakHashMap<>(); + @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { - Map chasers = getChasers(stack); - chasers.values().forEach(LerpedFloat::tickChaser); - putChasers(stack, chasers); - if (level.isClientSide()) { - if (getTool(stack) != selectedTool) DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(selectedTool)); + if (level.isClientSide() && entity == Minecraft.getInstance().player) { + ClientState clientState = getClientState(Minecraft.getInstance().player); + if (getTool(stack) != clientState.selectedTool) { + DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(clientState.selectedTool)); + }; }; }; @@ -136,8 +165,14 @@ public void initializeClient(Consumer consumer) { @OnlyIn(Dist.CLIENT) public static void clientPlayerTick() { Minecraft minecraft = Minecraft.getInstance(); + + clientStates.keySet().removeIf(entity -> !(entity.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem || entity.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)); + clientStates.forEach((entity, state) -> state.tick()); + LocalPlayer player = minecraft.player; if (player == null) return; + + ClientState clientState = getClientState(player); Tool newTool; boolean switchTool = false; if (!(player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem) && !(player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)) { @@ -152,10 +187,10 @@ public static void clientPlayerTick() { timeUntilToolPutAway = 20; }; }; - switchTool |= newTool != null && newTool != selectedTool; + switchTool |= newTool != null && newTool != clientState.selectedTool; if (switchTool) { DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(newTool)); - selectedTool = newTool; + clientState.selectedTool = newTool; }; }; @@ -200,36 +235,10 @@ public static Tool getTool(ItemStack stack) { public static void putTool(ItemStack stack, @Nullable Tool tool) { stack.removeTagKey("ActiveTool"); if (tool != null) stack.getOrCreateTag().putInt("ActiveTool", tool.ordinal()); - Map chasers = getChasers(stack); - chasers.entrySet().forEach(entry -> entry.getValue().chase(entry.getKey() == tool ? 1d : 0d, 0.4d, Chaser.EXP)); - putChasers(stack, chasers); }; - public static Map getChasers(ItemStack stack) { - EnumMap map = new EnumMap<>(Tool.class); - int ordinal = 0; - if (!stack.getOrCreateTag().contains("ToolAnimations", Tag.TAG_LIST)) return Tool.ALL_RETRACTED; - for (Tag t : stack.getOrCreateTag().getList("ToolAnimations", Tag.TAG_COMPOUND)) { - CompoundTag tag = (CompoundTag)t; - LerpedFloat toolAngle = LerpedFloat.angular().chase(tag.getFloat("Target"), 0.4d, Chaser.EXP); - toolAngle.setValue(tag.getFloat("Value")); - map.put(Tool.values()[ordinal], toolAngle); - ordinal++; - }; - return map; - }; - - public static void putChasers(ItemStack stack, Map chasers) { - ListTag list = new ListTag(); - for (Tool tool : Tool.values()) { - CompoundTag tag = new CompoundTag(); - LerpedFloat toolAngle = chasers.get(tool); - if (toolAngle == null) toolAngle = LerpedFloat.angular().chase(0d, 0.4d, Chaser.EXP); - tag.putFloat("Target", toolAngle.getChaseTarget()); - tag.putFloat("Value", toolAngle.getValue()); - list.add(tag); - }; - stack.getOrCreateTag().put("ToolAnimations", list); + public static ClientState getClientState(LivingEntity entity) { + return clientStates.computeIfAbsent(entity, e -> new ClientState()); }; public static enum Tool { diff --git a/src/main/java/com/petrolpark/destroy/item/renderer/SwissArmyKnifeRenderer.java b/src/main/java/com/petrolpark/destroy/item/renderer/SwissArmyKnifeRenderer.java index 0f38a9463..b28982887 100644 --- a/src/main/java/com/petrolpark/destroy/item/renderer/SwissArmyKnifeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/item/renderer/SwissArmyKnifeRenderer.java @@ -7,15 +7,18 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; +import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.item.SwissArmyKnifeItem; import com.petrolpark.destroy.item.SwissArmyKnifeItem.Tool; import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -29,11 +32,23 @@ public class SwissArmyKnifeRenderer extends CustomRenderedItemModelRenderer { protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { Minecraft mc = Minecraft.getInstance(); ItemRenderer itemRenderer = mc.getItemRenderer(); - if (transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND) { + + // animation only works for the local player for now + LivingEntity owner = null; + if(transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND) { + /*if(mc.player.getMainHandItem() == stack || mc.player.getOffhandItem() == stack) + owner = mc.player;*/ + + // eh + owner = mc.player; + } + + if (owner != null) { boolean firstPerson = (transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND); - Map chasers = SwissArmyKnifeItem.getChasers(stack); + Map chasers = SwissArmyKnifeItem.getClientState(owner).chasers; + float pt = AnimationTickHolder.getPartialTicks(); ms.pushPose(); if (!firstPerson) { @@ -61,7 +76,7 @@ protected void render(ItemStack stack, CustomRenderedItemModel model, PartialIte if (toolAngle != null) { TransformStack.cast(ms) .translate(5 / 16f, -5 / 16f, 0f) - .rotateZ(179 * (1 - toolAngle.getValue()) * (tool == RenderedTool.LOWER_SHEARS ? 1f : -1f)) + .rotateZ(179 * (1 - toolAngle.getValue(pt)) * (tool == RenderedTool.LOWER_SHEARS ? 1f : -1f)) .translateBack(5 / 16f, -5 / 16f, 0f); }; itemRenderer.renderStatic(renderedTool, ItemDisplayContext.NONE, light, OverlayTexture.NO_OVERLAY, ms, buffer, mc.level, 0); From ddcd6a8032d06a473625b2b5b796d38323569841 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Feb 2025 18:14:50 +0100 Subject: [PATCH 13/56] =?UTF-8?q?=F0=9F=92=A8=20Janky=20duct=20tape=20fix?= =?UTF-8?q?=20for=20Vat=20gas=20duplication?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/entity/VatControllerBlockEntity.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/block/entity/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/block/entity/VatControllerBlockEntity.java index 03bcb7edf..dd7f97216 100644 --- a/src/main/java/com/petrolpark/destroy/block/entity/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/block/entity/VatControllerBlockEntity.java @@ -790,12 +790,18 @@ protected FluidStack drainGasTank(int amount, FluidAction action) { protected FluidStack drainGasTankWithMolarDensity(int amount, double molarDensity, FluidAction action) { if (vatControllerGetter.get() == null || vatControllerGetter.get().getGasTankContents().isEmpty()) return FluidStack.EMPTY; LegacyMixture mixture = LegacyMixture.readNBT(vatControllerGetter.get().getGasTankContents().getOrCreateChildTag("Mixture")); + double scaleFactor = mixture.getTotalConcentration() / molarDensity; - FluidStack lostFluid = drainGasTank((int)Math.ceil(scaleFactor * amount), action); // Round up - mixture.scale((float)scaleFactor); - double drainedAmount = (double)lostFluid.getAmount() / scaleFactor; - FluidStack stack = MixtureFluid.of((int)Math.ceil(drainedAmount), mixture); - return stack; + int amountToDrain = Math.min((int)Math.ceil(scaleFactor * amount), amount); // Round up + FluidStack lostFluid = drainGasTank(amountToDrain, action); + + int drainedAmount = amount; + + // Don't bother scaling the mixture when simulating because this messes with Create's fluid networks + if(action.execute()) + mixture.scale((float)drainedAmount / lostFluid.getAmount()); + + return MixtureFluid.of(drainedAmount, mixture); }; protected void updateVatGasVolume(FluidStack drained, FluidAction action) { From 62721a6f14fdf68d7a53d80bbb6b2165b8ac39c1 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Feb 2025 18:16:02 +0100 Subject: [PATCH 14/56] =?UTF-8?q?=F0=9F=9A=B0=20Tentative=20fix=20for=20fl?= =?UTF-8?q?uid=20transfer=20getting=20stuck=20when=20pumping=20out=20of=20?= =?UTF-8?q?a=20reacting=20Vat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/mixin/FluidNetworkMixin.java | 32 +++++++++++++-- .../destroy/mixin/PipeConnectionMixin.java | 39 ++++++++++++++++++- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java index 923d04994..5caa90f1a 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java @@ -2,9 +2,16 @@ import java.util.Iterator; +import com.petrolpark.destroy.block.DestroyBlocks; +import com.tterrag.registrate.util.entry.BlockEntry; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.capability.IFluidHandler; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -20,11 +27,30 @@ @Mixin(FluidNetwork.class) public class FluidNetworkMixin { - + @Redirect( + method="Lcom/simibubi/create/content/fluids/FluidNetwork;tick()V", + at=@At( + value="INVOKE", + ordinal=0, + target="Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z" + ), + remap=false + ) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other) { + if(fluid.isFluidEqual(other)) + return true; + else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { + return true; + } + + return false; + } + /** * Similar to {@link com.petrolpark.destroy.mixin.PipeConnectionMixin here}, we don't want a Fluid Network to reset transferring Fluid if all that has changed * is one Mixture becoming another. */ + /* @Inject( method = "Lcom/simibubi/create/content/fluids/FluidNetwork;tick()V", at = @At( @@ -35,7 +61,7 @@ public class FluidNetworkMixin { cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT, remap = false - + ) public void inTick(CallbackInfo ci, int cycle, boolean shouldContinue, Iterator> iterator, Pair pair, BlockFace blockFace, PipeConnection pipeConnection, Flow flow) { FluidStack fluid = ((FluidNetworkAccessor)this).getFluid(); @@ -43,5 +69,5 @@ public void inTick(CallbackInfo ci, int cycle, boolean shouldContinue, Iterator< ((FluidNetworkAccessor)this).setFluid(flow.fluid); ci.cancel(); }; - }; + };*/ }; diff --git a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java index f4e765965..66c8f07c4 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java @@ -3,9 +3,12 @@ import java.util.Optional; import java.util.function.Predicate; +import com.petrolpark.destroy.Destroy; +import com.petrolpark.destroy.chemistry.legacy.LegacyMixture; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -23,7 +26,38 @@ @Mixin(PipeConnection.class) public class PipeConnectionMixin { - + private Optional retainedNetwork = Optional.empty(); + + @Inject( + method="Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", + at=@At("HEAD"), + remap=false + ) + private void onStartManageFlows(Level world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate, CallbackInfoReturnable cir) { + retainedNetwork = ((PipeConnectionAccessor)this).getNetwork(); + } + + @Redirect( + method="Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", + at=@At( + value="INVOKE", + target="Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z" + ), + remap=false + ) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other) { + if(fluid.isFluidEqual(other)) + return true; + else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { + ((PipeConnectionAccessor)this).getFlow().get().fluid = fluid; + if(retainedNetwork.isPresent()) + ((FluidNetworkAccessor)retainedNetwork.get()).setFluid(fluid); + return true; + } + + return false; + } + /** * Usually if a Fluid Network is trying to pull from a Tank and is animating the Fluid moving through the Pipes, it will * reset if the Fluid Stack changes. This stops this behaviour if the Fluid being transferred happens to be a Mixture, as @@ -34,6 +68,7 @@ public class PipeConnectionMixin { * @param extractionPredicate * @param cir */ +/* @Inject( method = "Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", at = @At( @@ -63,5 +98,5 @@ public void inManageFlows(Level world, BlockPos pos, FluidStack internalFluid, P cir.setReturnValue(true); // Let the client know an update has occured cir.cancel(); }; - }; + };*/ }; From 05610e1be37d257a4dd1c9646bbf0fb061429af9 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 15 Mar 2025 18:37:22 +0100 Subject: [PATCH 15/56] =?UTF-8?q?=E2=86=A9=EF=B8=8F=20Safer=20redirect=20f?= =?UTF-8?q?or=20FluidPropagatorMixin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++++ .../destroy/mixin/FluidPropagatorMixin.java | 23 +++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 43d10b909..2cd4e4939 100644 --- a/build.gradle +++ b/build.gradle @@ -217,6 +217,10 @@ dependencies { // ANNOTATION PROCESSORS annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor" + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) + implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1")) { + jarJar.ranged(it, "[0.4.1,)") + } } jar { diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java index a4f27da97..73f04039c 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java @@ -1,27 +1,26 @@ package com.petrolpark.destroy.mixin; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.petrolpark.destroy.DestroyBlocks; import com.simibubi.create.content.fluids.FluidPropagator; import com.tterrag.registrate.util.entry.BlockEntry; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(FluidPropagator.class) public class FluidPropagatorMixin { - - @Redirect( - method = "Lcom/simibubi/create/content/fluids/FluidPropagator;propagateChangedPipe(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V", - at = @At( - value = "INVOKE", - target = "Lcom/tterrag/registrate/util/entry/BlockEntry;has(Lnet/minecraft/world/level/block/state/BlockState;)Z", - remap = false + @WrapOperation( + method="Lcom/simibubi/create/content/fluids/FluidPropagator;propagateChangedPipe(Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V", + at=@At( + value="INVOKE", + target="Lcom/tterrag/registrate/util/entry/BlockEntry;has(Lnet/minecraft/world/level/block/state/BlockState;)Z", + remap=false ), remap=false ) - @SuppressWarnings("rawtypes") - private static boolean matchOtherPumps(BlockEntry instance, BlockState state) { - return instance.has(state) || DestroyBlocks.CREATIVE_PUMP.has(state); - }; + private static boolean matchOtherPumps(BlockEntry instance, BlockState state, Operation original) { + return DestroyBlocks.CREATIVE_PUMP.has(state) || original.call(instance, state); + } } From c4ce847a3bdb9b25f0350223d2e74f47c6c7d5bb Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 15 Mar 2025 18:38:53 +0100 Subject: [PATCH 16/56] =?UTF-8?q?=F0=9F=94=AA=20Clientside=20animation=20l?= =?UTF-8?q?ogic=20for=20Swiss=20Army=20Knife=20(for=20real=20this=20time)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swissarmyknife/SwissArmyKnifeItem.java | 108 ++++++++++-------- .../SwissArmyKnifeItemRenderer.java | 23 +++- 2 files changed, 76 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java index 8485d9b22..370d425c0 100644 --- a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java +++ b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java @@ -3,6 +3,7 @@ import java.util.EnumMap; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.function.Consumer; import java.util.function.Supplier; @@ -17,8 +18,6 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.tags.BlockTags; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -35,7 +34,6 @@ import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.CampfireBlock; import net.minecraft.world.level.block.PumpkinBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -53,20 +51,50 @@ public class SwissArmyKnifeItem extends DiggerItem { private static int timeUntilToolPutAway = 20; - @Nullable - public static Tool selectedTool = null; - public SwissArmyKnifeItem(float attackDamageModifier, float attackSpeedModifier, Tier tier, Properties properties) { super(attackDamageModifier, attackSpeedModifier, tier, BlockTags.MINEABLE_WITH_PICKAXE, properties); // The tag supplied here is ignored }; + @OnlyIn(Dist.CLIENT) + public static class ClientState { + @Nullable + public Tool selectedTool = null; + public Tool lastSelectedTool = null; + public int animTimer = 0; + + public Map chasers; + + public ClientState() { + chasers = new EnumMap<>(Tool.class); + for (Tool tool : Tool.values()) { + chasers.put(tool, LerpedFloat.angular().chase(0d, 0.4d, Chaser.EXP)); + }; + }; + + public void tick() { + chasers.values().forEach(chaser -> chaser.tickChaser()); + + if(selectedTool != lastSelectedTool) { + animTimer++; + if(animTimer >= 8) { + animTimer = 0; + lastSelectedTool = selectedTool; + chasers.forEach((entry, value) -> value.chase(entry == selectedTool ? 1d : 0d, 0.4d, Chaser.EXP)); + }; + }; + }; + }; + + @OnlyIn(Dist.CLIENT) + private static Map clientStates = new WeakHashMap<>(); + @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { - Map chasers = getChasers(stack); - chasers.values().forEach(LerpedFloat::tickChaser); - putChasers(stack, chasers); - if (level.isClientSide()) { - if (getTool(stack) != selectedTool) DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(selectedTool)); + if (level.isClientSide() && entity == Minecraft.getInstance().player) { + ClientState clientState = getClientState(Minecraft.getInstance().player); + if (getTool(stack) != clientState.selectedTool) { + DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(clientState.selectedTool)); + }; }; }; @@ -125,16 +153,22 @@ public boolean shouldCauseBlockBreakReset(ItemStack oldStack, ItemStack newStack }; @Override - @OnlyIn(Dist.CLIENT) - public void initializeClient(Consumer consumer) { - consumer.accept(SimpleCustomRenderer.create(this, new SwissArmyKnifeItemRenderer())); - }; + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + consumer.accept(SimpleCustomRenderer.create(this, new SwissArmyKnifeItemRenderer())); + }; @OnlyIn(Dist.CLIENT) public static void clientPlayerTick() { Minecraft minecraft = Minecraft.getInstance(); + + clientStates.keySet().removeIf(entity -> !(entity.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem || entity.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)); + clientStates.forEach((entity, state) -> state.tick()); + LocalPlayer player = minecraft.player; if (player == null) return; + + ClientState clientState = getClientState(player); Tool newTool; boolean switchTool = false; if (!(player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem) && !(player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)) { @@ -149,10 +183,10 @@ public static void clientPlayerTick() { timeUntilToolPutAway = 20; }; }; - switchTool |= newTool != null && newTool != selectedTool; + switchTool |= newTool != null && newTool != clientState.selectedTool; if (switchTool) { DestroyMessages.sendToServer(new SwissArmyKnifeToolC2SPacket(newTool)); - selectedTool = newTool; + clientState.selectedTool = newTool; }; }; @@ -175,7 +209,7 @@ public static Tool getTool(Level level, HitResult ray, boolean shiftDown) { if (shiftDown || tool == null) { if (state.getBlock() instanceof PumpkinBlock) tool = Tool.SHEARS; if (AxeItem.getAxeStrippingState(state) != null) tool = Tool.AXE; - if (ShovelItem.FLATTENABLES.containsKey(state.getBlock()) || (state.getBlock() instanceof CampfireBlock && state.getValue(CampfireBlock.LIT))) tool = Tool.SHOVEL; + if (ShovelItem.FLATTENABLES.containsKey(state.getBlock())) tool = Tool.SHOVEL; if (HoeItem.TILLABLES.containsKey(state.getBlock())) tool = Tool.HOE; }; } else if (ray instanceof EntityHitResult ehr) { @@ -197,36 +231,10 @@ public static Tool getTool(ItemStack stack) { public static void putTool(ItemStack stack, @Nullable Tool tool) { stack.removeTagKey("ActiveTool"); if (tool != null) stack.getOrCreateTag().putInt("ActiveTool", tool.ordinal()); - Map chasers = getChasers(stack); - chasers.entrySet().forEach(entry -> entry.getValue().chase(entry.getKey() == tool ? 1d : 0d, 0.4d, Chaser.EXP)); - putChasers(stack, chasers); - }; - - public static Map getChasers(ItemStack stack) { - EnumMap map = new EnumMap<>(Tool.class); - int ordinal = 0; - if (!stack.getOrCreateTag().contains("ToolAnimations", Tag.TAG_LIST)) return Tool.ALL_RETRACTED; - for (Tag t : stack.getOrCreateTag().getList("ToolAnimations", Tag.TAG_COMPOUND)) { - CompoundTag tag = (CompoundTag)t; - LerpedFloat toolAngle = LerpedFloat.angular().chase(tag.getFloat("Target"), 0.4d, Chaser.EXP); - toolAngle.setValue(tag.getFloat("Value")); - map.put(Tool.values()[ordinal], toolAngle); - ordinal++; - }; - return map; - }; - - public static void putChasers(ItemStack stack, Map chasers) { - ListTag list = new ListTag(); - for (Tool tool : Tool.values()) { - CompoundTag tag = new CompoundTag(); - LerpedFloat toolAngle = chasers.get(tool); - if (toolAngle == null) toolAngle = LerpedFloat.angular().chase(0d, 0.4d, Chaser.EXP); - tag.putFloat("Target", toolAngle.getChaseTarget()); - tag.putFloat("Value", toolAngle.getValue()); - list.add(tag); - }; - stack.getOrCreateTag().put("ToolAnimations", list); + }; + + public static ClientState getClientState(LivingEntity entity) { + return clientStates.computeIfAbsent(entity, e -> new ClientState()); }; public static enum Tool { @@ -249,5 +257,5 @@ public static enum Tool { this.exampleTool = exampleTool; }; }; - -}; + +}; \ No newline at end of file diff --git a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItemRenderer.java b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItemRenderer.java index 5cd3ce77a..235229d74 100644 --- a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItemRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItemRenderer.java @@ -11,6 +11,7 @@ import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.Minecraft; @@ -28,11 +29,23 @@ public class SwissArmyKnifeItemRenderer extends CustomRenderedItemModelRenderer protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemDisplayContext transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { Minecraft mc = Minecraft.getInstance(); ItemRenderer itemRenderer = mc.getItemRenderer(); - if (transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND) { + + // animation only works for the local player for now + LivingEntity owner = null; + if(transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND) { + /*if(mc.player.getMainHandItem() == stack || mc.player.getOffhandItem() == stack) + owner = mc.player;*/ + + // eh + owner = mc.player; + } + + if (owner != null) { boolean firstPerson = (transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND || transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND); - Map chasers = SwissArmyKnifeItem.getChasers(stack); + Map chasers = SwissArmyKnifeItem.getClientState(owner).chasers; + float pt = AnimationTickHolder.getPartialTicks(); ms.pushPose(); if (!firstPerson) { @@ -60,7 +73,7 @@ protected void render(ItemStack stack, CustomRenderedItemModel model, PartialIte if (toolAngle != null) { TransformStack.cast(ms) .translate(5 / 16f, -5 / 16f, 0f) - .rotateZ(179 * (1 - toolAngle.getValue()) * (tool == RenderedTool.LOWER_SHEARS ? 1f : -1f)) + .rotateZ(179 * (1 - toolAngle.getValue(pt)) * (tool == RenderedTool.LOWER_SHEARS ? 1f : -1f)) .translateBack(5 / 16f, -5 / 16f, 0f); }; itemRenderer.renderStatic(renderedTool, ItemDisplayContext.NONE, light, OverlayTexture.NO_OVERLAY, ms, buffer, mc.level, 0); @@ -107,5 +120,5 @@ public static float getItemProperty(ItemStack stack, @Nullable ClientLevel level }; - -}; + +}; \ No newline at end of file From 322e2fa13054b48bb5ea10b346a19e11bc256d50 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 15 Mar 2025 18:39:50 +0100 Subject: [PATCH 17/56] =?UTF-8?q?=F0=9F=AB=A5=20Fix=20mixtures=20in=20beak?= =?UTF-8?q?ers=20disappearing=20when=20looked=20at=20with=20Jade=20install?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/chemistry/storage/PlaceableMixtureTankBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankBlock.java b/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankBlock.java index 97c2b4700..38e71cb86 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankBlock.java @@ -56,7 +56,7 @@ public ItemStack getFilledItemStack(BlockEntity be) { if (be != null && asItem() instanceof IMixtureStorageItem mixtureItem) { ItemStack stack = new ItemStack(asItem()); return be.getCapability(ForgeCapabilities.FLUID_HANDLER).map(fluidHandler -> { - mixtureItem.setContents(stack, fluidHandler.drain(mixtureItem.getCapacity(stack), FluidAction.EXECUTE)); + mixtureItem.setContents(stack, fluidHandler.drain(mixtureItem.getCapacity(stack), FluidAction.SIMULATE)); return stack; }).orElse(ItemStack.EMPTY); }; From 12083727143c5585d4df53882d3535e33d7984c3 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 15 Mar 2025 18:40:39 +0100 Subject: [PATCH 18/56] =?UTF-8?q?=E2=98=A2=EF=B8=8F=20Fix=20pollutometer?= =?UTF-8?q?=20reading=20radiation=20levels=20instead=20of=20greenhouse=20g?= =?UTF-8?q?ases=20when=20first=20placed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/pollution/pollutometer/PollutometerBlockEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/core/pollution/pollutometer/PollutometerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/pollution/pollutometer/PollutometerBlockEntity.java index 8de2d1f98..76f3e2d28 100644 --- a/src/main/java/com/petrolpark/destroy/core/pollution/pollutometer/PollutometerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/pollution/pollutometer/PollutometerBlockEntity.java @@ -28,7 +28,7 @@ public class PollutometerBlockEntity extends SmartBlockEntity { public PollutometerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); - pollutionType = PollutionType.RADIOACTIVITY; + pollutionType = PollutionType.GREENHOUSE; }; @Override From e6f912a4707e09e7c95ad27c55e118da18c8577c Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 15 Mar 2025 19:50:16 +0100 Subject: [PATCH 19/56] =?UTF-8?q?=F0=9F=92=AC=20Language=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StackedTextBoxComponent.java | 18 ++++++++++++++---- .../resources/assets/destroy/lang/en_gb.json | 4 ++-- .../resources/assets/destroy/lang/en_us.json | 4 ++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/client/stackedtextbox/StackedTextBoxComponent.java b/src/main/java/com/petrolpark/destroy/client/stackedtextbox/StackedTextBoxComponent.java index dbbd20925..0f262ff38 100644 --- a/src/main/java/com/petrolpark/destroy/client/stackedtextbox/StackedTextBoxComponent.java +++ b/src/main/java/com/petrolpark/destroy/client/stackedtextbox/StackedTextBoxComponent.java @@ -5,6 +5,7 @@ import java.util.List; import com.petrolpark.destroy.MoveToPetrolparkLibrary; +import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; import com.petrolpark.destroy.config.DestroyAllConfigs; import net.minecraft.client.Minecraft; @@ -56,10 +57,19 @@ public static class Molecule extends Plain { public Molecule(String value) { super(value); - String[] nameSpaceAndId = value.split(":"); - String key = nameSpaceAndId[0] + ".chemical." + nameSpaceAndId[1]; - String iupacKey = key + ".iupac"; - if (DestroyAllConfigs.CLIENT.chemistry.iupacNames.get() && I18n.exists(iupacKey)) key = iupacKey; + LegacySpecies sp = LegacySpecies.getMolecule(value); + String key; + + if(sp != null) + key = sp.getTranslationKey(DestroyAllConfigs.CLIENT.chemistry.iupacNames.get()); + else + { + String[] nameSpaceAndId = value.split(":"); + key = nameSpaceAndId[0] + ".chemical." + nameSpaceAndId[1]; + String iupacKey = key + ".iupac"; + if (DestroyAllConfigs.CLIENT.chemistry.iupacNames.get() && I18n.exists(iupacKey)) key = iupacKey; + } + String moleculeName = Component.translatable(key).getString(); setWords(moleculeName); }; diff --git a/src/main/resources/assets/destroy/lang/en_gb.json b/src/main/resources/assets/destroy/lang/en_gb.json index 9bd7781b5..065d13f73 100644 --- a/src/main/resources/assets/destroy/lang/en_gb.json +++ b/src/main/resources/assets/destroy/lang/en_gb.json @@ -1294,7 +1294,7 @@ "destroy.reaction.hydrogen_combustion": "[destroy:hydrogen] Combustion", "destroy.reaction.hydrogen_combustion.description": "The highly {exothermic, destroy:exothermic} {oxidation, destroy:oxidation} of [destroy:hydrogen].", "destroy.reaction.hydrogen_cyanide_dissociation": "[destroy:hydrogen_cyanide] Dissociation", - "destroy.reaction.hydrogen_cyanide_dissociation.description": "Hydrogen cyanide is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {destroy:base}.", + "destroy.reaction.hydrogen_cyanide_dissociation.description": "Hydrogen cyanide is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.hydrogen_iodide_synthesis": "[destroy:hydrogen_iodide] Synthesis", "destroy.reaction.hydrogen_iodide_synthesis.description": "A method for the production of [destroy:hydrogen_iodide].", "destroy.reaction.hydroxide_neutralization": "Neutralisation", @@ -1302,7 +1302,7 @@ "destroy.reaction.hypochlorite_formation": "[destroy:hypochlorite] Formation", "destroy.reaction.hypochlorite_formation.description": "The {disproportionation, destroy:disproportionation} of [destroy:chlorine] with sodium hydroxide.", "destroy.reaction.hypochlorous_acid_dissociation": "[destroy:hypochlorous_acid] Dissociation", - "destroy.reaction.hypochlorous_acid_dissociation.description": "Hypochlorous Acid is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {destroy:base}.", + "destroy.reaction.hypochlorous_acid_dissociation.description": "Hypochlorous Acid is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.iodide_displacement": "[destroy:iodide] Displacement", "destroy.reaction.iodide_displacement.description": "The {oxidation, destroy:oxidation} of [destroy:iodide] and {reduction, destroy:reduction} of [destroy:chlorine].", "destroy.reaction.iodine_dissolution": "[destroy:iodine] Solution", diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index 5740d202b..dbd014b6a 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -1166,7 +1166,7 @@ "destroy.reaction.hydrogen_combustion": "[destroy:hydrogen] Combustion", "destroy.reaction.hydrogen_combustion.description": "The highly {exothermic, destroy:exothermic} {oxidation, destroy:oxidation} of [destroy:hydrogen].", "destroy.reaction.hydrogen_cyanide_dissociation": "[destroy:hydrogen_cyanide] Dissociation", - "destroy.reaction.hydrogen_cyanide_dissociation.description": "Hydrogen cyanide is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {destroy:base}.", + "destroy.reaction.hydrogen_cyanide_dissociation.description": "Hydrogen cyanide is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.hydrogen_iodide_synthesis": "[destroy:hydrogen_iodide] Synthesis", "destroy.reaction.hydrogen_iodide_synthesis.description": "A method for the production of [destroy:hydrogen_iodide].", "destroy.reaction.hydroxide_neutralization": "Neutralization", @@ -1174,7 +1174,7 @@ "destroy.reaction.hypochlorite_formation": "[destroy:hypochlorite] Formation", "destroy.reaction.hypochlorite_formation.description": "The {disproportionation, destroy:disproportionation} of [destroy:chlorine] with sodium hydroxide.", "destroy.reaction.hypochlorous_acid_dissociation": "[destroy:hypochlorous_acid] Dissociation", - "destroy.reaction.hypochlorous_acid_dissociation.description": "Hypochlorous Acid is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {destroy:base}.", + "destroy.reaction.hypochlorous_acid_dissociation.description": "Hypochlorous Acid is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.iodide_displacement": "[destroy:iodide] Displacement", "destroy.reaction.iodide_displacement.description": "The {oxidation, destroy:oxidation} of [destroy:iodide] and {reduction, destroy:reduction} of [destroy:chlorine].", "destroy.reaction.iodine_dissolution": "[destroy:iodine] Solution", From 7ef19b2f0ef02b6f9b94d6bb34828fd4f24ef62c Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 16 Mar 2025 16:03:20 +0100 Subject: [PATCH 20/56] =?UTF-8?q?=F0=9F=A7=8A=20Fix=20KubeJS=20removing=20?= =?UTF-8?q?circuit=20boards=20from=20recipes=20that=20contain=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trypolithography/recipe/CircuitPatternIngredient.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/recipe/CircuitPatternIngredient.java b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/recipe/CircuitPatternIngredient.java index e3729c410..4f76cc4ad 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/recipe/CircuitPatternIngredient.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/recipe/CircuitPatternIngredient.java @@ -50,6 +50,9 @@ public boolean isSimple() { return false; }; + @Override + public boolean isEmpty() { return false; }; + @Override public IIngredientSerializer getSerializer() { return SERIALIZER; From f19b87f63af61721ac58a46bb561c207cc1445e3 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 11:25:53 +0100 Subject: [PATCH 21/56] =?UTF-8?q?=F0=9F=9B=A2=EF=B8=8F=20Temporary=20fix?= =?UTF-8?q?=20for=20TFMG=20compatibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cursed problems require cursed solutions --- build.gradle | 52 +++++++++++++++--- gradle.properties | 10 +++- .../destroy/mixin/FluidNetworkMixin.java | 50 ++--------------- .../destroy/mixin/FluidPropagatorMixin.java | 4 +- .../destroy/mixin/PipeConnectionMixin.java | 55 ++++--------------- .../mixin/plugin/DestroyMixinPlugin.java | 6 ++ 6 files changed, 76 insertions(+), 101 deletions(-) diff --git a/build.gradle b/build.gradle index 78cb8455a..05fd97cfc 100644 --- a/build.gradle +++ b/build.gradle @@ -150,6 +150,28 @@ repositories { maven { // Blueprint url = "https://maven.jaackson.me" } + + maven { // Architectury + url = "https://maven.architectury.dev" + content { + includeGroup "dev.architectury" + } + } + maven { // KubeJS and Rhino + url = "https://maven.saps.dev/minecraft" + content { + includeGroup "dev.latvian.mods" + } + } + + maven { // EMI + name = "TerraformersMC" + url = "https://maven.terraformersmc.com/" + } + + maven { // MixinSquared (may god have mercy) + url = "https://maven.bawnorton.com/releases" + } } configurations { @@ -195,7 +217,7 @@ dependencies { // JEI compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}") compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") - compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") + implementation fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") // Farmer's Delight compileOnly fg.deobf("curse.maven:farmers-delight-398521:${farmersdelight_version}") @@ -205,22 +227,36 @@ dependencies { runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${minecraft_version}") // TFMG - compileOnly fg.deobf("curse.maven:create-industry-693815:5558101") + implementation fg.deobf("curse.maven:create-industry-693815:5558101") // CBC implementation fg.deobf("com.rbasamoyai:ritchiesprojectilelib:1.0.0-369e88d+1.20.1-forge") implementation fg.deobf("com.rbasamoyai:createbigcannons:${cbc_version}") // Embeddium - compileOnly fg.deobf("maven.modrinth:embeddium:${embeddium_version}+mc${minecraft_version}") - + implementation fg.deobf("maven.modrinth:embeddium:${embeddium_version}+mc${minecraft_version}") + + // Jade + runtimeOnly fg.deobf("maven.modrinth:jade:${jade_version}") + + // KubeJS + runtimeOnly fg.deobf("dev.latvian.mods:rhino-forge:${rhino_version}") + runtimeOnly fg.deobf("dev.latvian.mods:kubejs-forge:${kubejs_version}") + runtimeOnly fg.deobf("dev.architectury:architectury-forge:${architectury_version}") + + implementation fg.deobf("maven.modrinth:sophisticated-core:1.20.1-1.2.23.902") + runtimeOnly fg.deobf("maven.modrinth:sophisticated-backpacks:1.20.1-3.23.6.1211") + // ANNOTATION PROCESSORS + // MixinSquared's annotationProcessor MUST be registered BEFORE Mixin's one. + compileOnly(annotationProcessor("com.github.bawnorton.mixinsquared:mixinsquared-common:${mixin_squared_version}")) + implementation(jarJar("com.github.bawnorton.mixinsquared:mixinsquared-forge:${mixin_squared_version}")) {jarJar.ranged(it, "[${mixin_squared_version},)")} + annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor" - compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) - implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1")) { - jarJar.ranged(it, "[0.4.1,)") - } + + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${mixin_extras_version}")) + implementation(jarJar("io.github.llamalad7:mixinextras-forge:${mixin_extras_version}")) {jarJar.ranged(it, "[${mixin_extras_version},)")} } jar { diff --git a/gradle.properties b/gradle.properties index a0c10858f..b75b0b4fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,8 @@ forgegradle_version = 6.0.26 cursegradle_version = 1.4.0 mixingradle_version = 0.7-SNAPSHOT mixin_version = 0.8.5 +mixin_extras_version = 0.4.1 +mixin_squared_version = 0.2.0 librarian_version = 1.+ parchment_version = 2023.09.03 @@ -21,10 +23,16 @@ flywheel_version = 0.6.11-13 registrate_version = MC1.20-1.3.3 # Optional mod dependency info -jei_version = 15.12.3.55 +jei_version = 15.20.0.106 farmersdelight_version = 4638874 blueprint_version = 7.0.0 spark_version = 4587309 cbc_version = 5.5.0+mc.1.20.1-forge curios_version = 5.9.1 embeddium_version = 0.3.30 + +jade_version = 11.12.3+forge +kubejs_version = 2001.6.5-build.18 +rhino_version = 2001.2.3-build.10 +architectury_version = 9.2.14 +emi_version = 1.1.20+1.20.1 \ No newline at end of file diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java index 1bc30c883..525d7ed1e 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidNetworkMixin.java @@ -1,33 +1,18 @@ package com.petrolpark.destroy.mixin; -import java.util.Iterator; - -import com.petrolpark.destroy.block.DestroyBlocks; -import com.tterrag.registrate.util.entry.BlockEntry; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.capability.IFluidHandler; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import com.petrolpark.destroy.DestroyFluids; -import com.petrolpark.destroy.mixin.accessor.FluidNetworkAccessor; import com.simibubi.create.content.fluids.FluidNetwork; -import com.simibubi.create.content.fluids.PipeConnection; -import com.simibubi.create.content.fluids.PipeConnection.Flow; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Pair; import net.minecraftforge.fluids.FluidStack; @Mixin(FluidNetwork.class) public class FluidNetworkMixin { - @Redirect( + @WrapOperation( method="Lcom/simibubi/create/content/fluids/FluidNetwork;tick()V", at=@At( value="INVOKE", @@ -36,8 +21,8 @@ public class FluidNetworkMixin { ), remap=false ) - private boolean considerMixturesEqual(FluidStack fluid, FluidStack other) { - if(fluid.isFluidEqual(other)) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operation original) { + if(original.call(fluid, other)) return true; else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { return true; @@ -45,29 +30,4 @@ else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { return false; } - - /** - * Similar to {@link com.petrolpark.destroy.mixin.PipeConnectionMixin here}, we don't want a Fluid Network to reset transferring Fluid if all that has changed - * is one Mixture becoming another. - */ - /* - @Inject( - method = "Lcom/simibubi/create/content/fluids/FluidNetwork;tick()V", - at = @At( - value = "INVOKE", - target = "Ljava/util/Iterator;remove()V", - ordinal = 1 - ), - cancellable = true, - locals = LocalCapture.CAPTURE_FAILSOFT, - remap = false - - ) - public void inTick(CallbackInfo ci, int cycle, boolean shouldContinue, Iterator> iterator, Pair pair, BlockFace blockFace, PipeConnection pipeConnection, Flow flow) { - FluidStack fluid = ((FluidNetworkAccessor)this).getFluid(); - if (DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(flow.fluid)) { - ((FluidNetworkAccessor)this).setFluid(flow.fluid); - ci.cancel(); - }; - };*/ }; diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java index 73f04039c..366e5e6b5 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidPropagatorMixin.java @@ -2,8 +2,8 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.petrolpark.destroy.DestroyBlocks; import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.pump.PumpBlock; import com.tterrag.registrate.util.entry.BlockEntry; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @@ -21,6 +21,6 @@ public class FluidPropagatorMixin { remap=false ) private static boolean matchOtherPumps(BlockEntry instance, BlockState state, Operation original) { - return DestroyBlocks.CREATIVE_PUMP.has(state) || original.call(instance, state); + return (state.getBlock() instanceof PumpBlock) || original.call(instance, state); } } diff --git a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java index 48c078c12..463417007 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java @@ -3,6 +3,8 @@ import java.util.Optional; import java.util.function.Predicate; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.chemistry.legacy.LegacyMixture; import org.spongepowered.asm.mixin.Mixin; @@ -37,7 +39,12 @@ private void onStartManageFlows(Level world, BlockPos pos, FluidStack internalFl retainedNetwork = ((PipeConnectionAccessor)this).getNetwork(); } - @Redirect( + /** + * Usually if a Fluid Network is trying to pull from a Tank and is animating the Fluid moving through the Pipes, it will + * reset if the Fluid Stack changes. This stops this behaviour if the Fluid being transferred happens to be a Mixture, as + * these change a lot. We don't want to try restarting the flow every tick. + */ + @WrapOperation( method="Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", at=@At( value="INVOKE", @@ -45,8 +52,8 @@ private void onStartManageFlows(Level world, BlockPos pos, FluidStack internalFl ), remap=false ) - private boolean considerMixturesEqual(FluidStack fluid, FluidStack other) { - if(fluid.isFluidEqual(other)) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operation original) { + if(original.call(fluid, other)) return true; else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { ((PipeConnectionAccessor)this).getFlow().get().fluid = fluid; @@ -57,46 +64,4 @@ else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { return false; } - - /** - * Usually if a Fluid Network is trying to pull from a Tank and is animating the Fluid moving through the Pipes, it will - * reset if the Fluid Stack changes. This stops this behaviour if the Fluid being transferred happens to be a Mixture, as - * these change a lot. We don't want to try restarting the flow every tick. - * @param world - * @param pos - * @param internalFluid - * @param extractionPredicate - * @param cir - */ -/* - @Inject( - method = "Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", - at = @At( - value = "INVOKE", - target = "empty", - ordinal = 1 - ), - cancellable = true, - locals = LocalCapture.CAPTURE_FAILSOFT, - remap = false - ) - public void inManageFlows(Level world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate, CallbackInfoReturnable cir, Optional retainedNetwork) { - Flow flow = ((PipeConnectionAccessor)this).getFlow().get(); - FlowSource source = ((PipeConnectionAccessor)this).getSource().get(); - - FluidStack provided = flow.inbound ? source.provideFluid(extractionPredicate) : internalFluid; - if (((PipeConnection)(Object)this).hasPressure() && DestroyFluids.isMixture(provided) && DestroyFluids.isMixture(flow.fluid)) { // Only update the Fluid if we have Fluid and should be moving it - flow.fluid = provided; - Optional network = retainedNetwork; - if (network.isPresent()) { - ((FluidNetworkAccessor)network.get()).setFluid(provided.copy()); - ((PipeConnectionAccessor)this).setNetwork(network); - }; - - ((PipeConnection)(Object)this).manageFlows(world, pos, internalFluid, extractionPredicate); - - cir.setReturnValue(true); // Let the client know an update has occured - cir.cancel(); - }; - };*/ }; diff --git a/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java b/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java index b0d05dc37..24c712af7 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java @@ -1,6 +1,8 @@ package com.petrolpark.destroy.mixin.plugin; +import com.bawnorton.mixinsquared.canceller.MixinCancellerRegistrar; import com.petrolpark.compat.CompatMods; +import com.petrolpark.destroy.Destroy; import com.petrolpark.mixin.plugin.PetrolparkMixinPlugin; public class DestroyMixinPlugin extends PetrolparkMixinPlugin { @@ -14,6 +16,10 @@ protected String getMixinPackage() { public void onLoad(String mixinPackage) { // TFMG mixins requireMultipleMods("AdvancedDistillationCategoryMixin", CompatMods.TFMG, CompatMods.JEI); + + // Fixes a compatibility issue with TFMG caused by the way it registers its own custom pumps + // Not a permanent solution (hopefully) + MixinCancellerRegistrar.register((targetClassNames, mixinClassName) -> mixinClassName.equals("com.drmangotea.tfmg.mixins.FluidPropagatorMixin")); }; }; From 97bf0ec97546cb610b17bb8bc4179e69b524726d Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 20:40:56 +0100 Subject: [PATCH 22/56] =?UTF-8?q?=F0=9F=91=93=20Less=20buggy=20Colorimeter?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed Colorimeters breaking when unloaded - Fixed Colorimeters not properly displaying their monitored value in the GUI - Changing the threshold values on Colorimeters and Vat pressure/temperature sensors now only takes effect when closing the GUI --- .../AbstractQuantityObservingScreen.java | 20 ++++----- .../RedstoneMonitorVatSideScreen.java | 6 +-- .../RedstoneQuantityMonitorBehaviour.java | 24 +++++++---- ...antityMonitorThresholdChangeC2SPacket.java | 20 ++++----- .../colorimeter/ColorimeterBlock.java | 16 ++++--- .../colorimeter/ColorimeterBlockEntity.java | 42 +++++++++++++++---- .../colorimeter/ColorimeterScreen.java | 14 +++---- 7 files changed, 92 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/AbstractQuantityObservingScreen.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/AbstractQuantityObservingScreen.java index d4c5393e3..a2c4f2524 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/AbstractQuantityObservingScreen.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/AbstractQuantityObservingScreen.java @@ -3,6 +3,7 @@ import java.util.List; import com.mojang.blaze3d.platform.InputConstants; +import com.petrolpark.destroy.DestroyMessages; import com.petrolpark.destroy.client.DestroyGuiTextures; import com.petrolpark.destroy.client.DestroyLang; import com.simibubi.create.foundation.gui.AbstractSimiScreen; @@ -38,7 +39,7 @@ protected int getTitleX() { return 16; }; - protected abstract void onThresholdChange(boolean upper, float newValue); + protected abstract void updateThresholds(float lower, float upper); @Override protected void init() { @@ -60,6 +61,7 @@ protected void init() { lowerBound.mouseClicked(0, 0, 0); lowerBound.active = false; lowerBound.setTooltip(Tooltip.create(DestroyLang.translate("tooltip.vat.menu.quantity_observed.minimum").component())); + lowerBound.setValue(""+quantityBehaviour.lowerThreshold); upperBound = new EditBox(minecraft.font, guiLeft + 171, guiTop + getEditBoxY(), 70, 10, Component.literal(""+quantityBehaviour.lowerThreshold)); upperBound.setBordered(false); @@ -68,6 +70,7 @@ protected void init() { upperBound.mouseClicked(0, 0, 0); upperBound.active = false; upperBound.setTooltip(Tooltip.create(DestroyLang.translate("tooltip.vat.menu.quantity_observed.maximum").component())); + upperBound.setValue(""+quantityBehaviour.upperThreshold); addRenderableWidgets(lowerBound, upperBound); }; @@ -80,15 +83,7 @@ public void tick() { box.setCursorPosition(box.getValue().length()); box.setHighlightPos(box.getCursorPosition()); - // Attempt to update the Vat Side with the given number - boolean upper = box == upperBound; - float oldValue = upper ? quantityBehaviour.upperThreshold : quantityBehaviour.lowerThreshold; - try { - float value = Float.valueOf(box.getValue()); - if (value != oldValue) onThresholdChange(upper, value); - } catch (NumberFormatException e) { - box.setValue(""+oldValue); - }; + // TODO: validate values }; }; }; @@ -98,6 +93,11 @@ public void onClose() { lowerBound.setFocused(false); upperBound.setFocused(false); tick(); + + try { + updateThresholds(Float.valueOf(lowerBound.getValue()), Float.valueOf(upperBound.getValue())); + } catch (NumberFormatException e) {} + super.onClose(); } diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneMonitorVatSideScreen.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneMonitorVatSideScreen.java index 84d68f004..84aa7efe6 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneMonitorVatSideScreen.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneMonitorVatSideScreen.java @@ -20,8 +20,8 @@ protected int getEditBoxY() { }; @Override - protected void onThresholdChange(boolean upper, float newValue) { - DestroyMessages.sendToServer(new RedstoneQuantityMonitorThresholdChangeC2SPacket(upper, newValue, vatSide.getBlockPos())); - }; + protected void updateThresholds(float lower, float upper) { + DestroyMessages.sendToServer(new RedstoneQuantityMonitorThresholdChangeC2SPacket(lower, upper, vatSide.getBlockPos())); + } }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorBehaviour.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorBehaviour.java index 586d7a00a..9a26191fb 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorBehaviour.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorBehaviour.java @@ -7,6 +7,8 @@ import javax.annotation.Nonnull; +import com.petrolpark.destroy.Destroy; +import com.petrolpark.destroy.core.chemistry.vat.observation.colorimeter.ColorimeterBlockEntity; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; @@ -26,6 +28,7 @@ public class RedstoneQuantityMonitorBehaviour extends BlockEntityBehaviour { public float lowerThreshold; public float upperThreshold; protected int oldStrength; + protected boolean isFirstTick; protected IntConsumer strengthChangeCallback = i -> {}; @@ -34,6 +37,11 @@ public RedstoneQuantityMonitorBehaviour(SmartBlockEntity be) { quantityObserved = Optional.empty(); }; + @Override + public void initialize() { + isFirstTick = true; + } + public RedstoneQuantityMonitorBehaviour withLabel(Function label) { this.label = label; return this; @@ -45,8 +53,7 @@ public RedstoneQuantityMonitorBehaviour onStrengthChanged(IntConsumer callback) }; public int getStrength() { - if (quantityObserved.isPresent()) return oldStrength; - return 0; + return oldStrength; }; public void update() { @@ -60,6 +67,11 @@ public Component getLabelledQuantity() { @Override public void tick() { + if(isFirstTick) { + isFirstTick = false; + return; + } + int strength = 0; if (quantityObserved.isPresent()) strength = (int)(Mth.clamp((quantityObserved.get().get() - lowerThreshold) / (upperThreshold - lowerThreshold), 0f, 1f) * 15f); if (strength != oldStrength) { @@ -80,11 +92,9 @@ public void read(CompoundTag nbt, boolean clientPacket) { @Override public void write(CompoundTag nbt, boolean clientPacket) { super.write(nbt, clientPacket); - if (quantityObserved.isPresent()) { - nbt.putInt("OldRedstoneStrength", oldStrength); - nbt.putFloat("LowerObservedQuantityThreshold", lowerThreshold); - nbt.putFloat("UpperObservedQuantityThreshold", upperThreshold); - }; + nbt.putInt("OldRedstoneStrength", oldStrength); + nbt.putFloat("LowerObservedQuantityThreshold", lowerThreshold); + nbt.putFloat("UpperObservedQuantityThreshold", upperThreshold); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorThresholdChangeC2SPacket.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorThresholdChangeC2SPacket.java index 266fcd0bd..0a7ad8f7b 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorThresholdChangeC2SPacket.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/RedstoneQuantityMonitorThresholdChangeC2SPacket.java @@ -12,26 +12,26 @@ public class RedstoneQuantityMonitorThresholdChangeC2SPacket extends C2SPacket { - public final boolean upper; - public final float value; + public final float lower; + public final float upper; public final BlockPos pos; - public RedstoneQuantityMonitorThresholdChangeC2SPacket(boolean upper, float value, BlockPos pos) { + public RedstoneQuantityMonitorThresholdChangeC2SPacket(float lower, float upper, BlockPos pos) { + this.lower = lower; this.upper = upper; - this.value = value; this.pos = pos; }; public RedstoneQuantityMonitorThresholdChangeC2SPacket(FriendlyByteBuf buffer) { - upper = buffer.readBoolean(); - value = buffer.readFloat(); + lower = buffer.readFloat(); + upper = buffer.readFloat(); pos = buffer.readBlockPos(); }; @Override public void toBytes(FriendlyByteBuf buffer) { - buffer.writeBoolean(upper); - buffer.writeFloat(value); + buffer.writeFloat(lower); + buffer.writeFloat(upper); buffer.writeBlockPos(pos); }; @@ -42,8 +42,8 @@ public boolean handle(Supplier supplier) { ServerPlayer sender = context.getSender(); RedstoneQuantityMonitorBehaviour behaviour = BlockEntityBehaviour.get(sender.level(), pos, RedstoneQuantityMonitorBehaviour.TYPE); if (behaviour != null) { - if (upper) behaviour.upperThreshold = value; - else behaviour.lowerThreshold = value; + behaviour.lowerThreshold = lower; + behaviour.upperThreshold = upper; behaviour.notifyUpdate(); }; }); diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlock.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlock.java index 18a567cbf..fc4422345 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlock.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; +import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.DestroyBlockEntityTypes; import com.petrolpark.destroy.DestroyFluids; import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; @@ -13,11 +14,15 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlockEntity; import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.gui.ScreenOpener; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -79,14 +84,15 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player if (DestroyFluids.isMixture(fluid)) species.addAll(ReadOnlyMixture.readNBT(ReadOnlyMixture::new, fluid.getOrCreateChildTag("Mixture")).getContents(false)); }; - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(be, species)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(be, species, player)); return InteractionResult.SUCCESS; }); }; @OnlyIn(Dist.CLIENT) - public void openScreen(ColorimeterBlockEntity be, Set species) { - ScreenOpener.open(new ColorimeterScreen(be, new ArrayList<>(species))); + public void openScreen(ColorimeterBlockEntity be, Set species, Player player) { + if(player instanceof LocalPlayer) + ScreenOpener.open(new ColorimeterScreen(be, new ArrayList<>(species))); }; @Override @@ -101,8 +107,8 @@ public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Directio }; @Override - public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { - withBlockEntityDo(level, pos, ColorimeterBlockEntity::updateVat); + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos neighborPos, boolean isMoving) { + withBlockEntityDo(level, pos, cbe -> cbe.onNeighborChanged(neighborPos)); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java index ee7e75148..b17a7c14c 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Optional; +import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.DestroyAdvancementTrigger; import com.petrolpark.destroy.DestroyBlockEntityTypes; import com.petrolpark.destroy.DestroyFluids; @@ -16,20 +17,24 @@ import com.petrolpark.destroy.core.chemistry.vat.material.VatMaterial; import com.petrolpark.destroy.core.chemistry.vat.observation.RedstoneQuantityMonitorBehaviour; import com.petrolpark.destroy.core.data.advancement.DestroyAdvancementBehaviour; +import com.simibubi.create.api.event.BlockEntityBehaviourEvent; import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.FluidStack; public class ColorimeterBlockEntity extends SmartBlockEntity { @@ -45,33 +50,48 @@ public class ColorimeterBlockEntity extends SmartBlockEntity { public RedstoneQuantityMonitorBehaviour redstoneMonitor; protected DestroyAdvancementBehaviour advancementBehaviour; + protected boolean updateVatNextTick; public ColorimeterBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); }; + public void initialize() { + super.initialize(); + updateVatNextTick = true; + } + @Override public void addBehaviours(List behaviours) { + advancementBehaviour = new DestroyAdvancementBehaviour(this, DestroyAdvancementTrigger.COLORIMETER); + behaviours.add(advancementBehaviour); + redstoneMonitor = new RedstoneQuantityMonitorBehaviour(this) .withLabel(f -> DestroyLang.translate("tooltip.colorimeter.menu.current_concentration", df.format(f)).component()) .onStrengthChanged(strength -> getLevel().setBlockAndUpdate(getBlockPos(), getBlockState().setValue(ColorimeterBlock.POWERED, strength != 0))); behaviours.add(redstoneMonitor); - - advancementBehaviour = new DestroyAdvancementBehaviour(this, DestroyAdvancementTrigger.COLORIMETER); - behaviours.add(advancementBehaviour); }; - + @Override public void tick() { super.tick(); if (molecule != null && getVatOptional().isPresent()) advancementBehaviour.awardDestroyAdvancement(DestroyAdvancementTrigger.COLORIMETER); + + if(updateVatNextTick) + { + updateVatNextTick = false; + updateVat(); + } }; @Override protected void read(CompoundTag tag, boolean clientPacket) { super.read(tag, clientPacket); - setMolecule(LegacySpecies.getMolecule(tag.getString("Molecule"))); - if (tag.contains("ObservingGas")) observingGas = true; + + if(clientPacket && (Minecraft.getInstance().screen instanceof ColorimeterScreen cs) && cs.colorimeter == this) + return; + + configure(LegacySpecies.getMolecule(tag.getString("Molecule")), tag.contains("ObservingGas")); }; @Override @@ -84,6 +104,7 @@ protected void write(CompoundTag tag, boolean clientPacket) { public void configure(LegacySpecies observedMolecule, boolean observingGas) { this.observingGas = observingGas; setMolecule(observedMolecule); + updateVatNextTick = true; }; public LegacySpecies getMolecule() { @@ -92,7 +113,6 @@ public LegacySpecies getMolecule() { public void setMolecule(LegacySpecies molecule) { this.molecule = molecule; - updateVat(); notifyUpdate(); }; @@ -105,8 +125,14 @@ public Optional getVatOptional() { }); }; + public void onNeighborChanged(BlockPos neighborPos) { + if(neighborPos.equals(getBlockPos().relative(getBlockState().getValue(ColorimeterBlock.FACING)))) + updateVatNextTick = true; + } + public void updateVat() { Optional vat = getVatOptional(); + Destroy.LOGGER.info("updated vat {}", vat); if (molecule != null && vat.isPresent()) { redstoneMonitor.quantityObserved = Optional.of(() -> { FluidStack mixtureStack = (observingGas ? vat.get().getGasTankContents() : vat.get().getLiquidTankContents()); @@ -120,7 +146,7 @@ public void updateVat() { }; redstoneMonitor.quantityObserved = Optional.empty(); }; - + public static class ColorimeterDisplaySource extends DisplaySource { private static final DecimalFormat df = new DecimalFormat(); diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java index 63dbd3cb0..a9a7a005b 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java @@ -42,8 +42,8 @@ public ColorimeterScreen(ColorimeterBlockEntity colorimeter, List species = colorimeter.getMolecule(); speciesIndex = 0; this.availableSpecies = availableSpecies; - availableSpecies.remove(species); - availableSpecies.add(speciesIndex, species); // Put the selected species first + + speciesIndex = availableSpecies.indexOf(species); observingGas = colorimeter.observingGas; }; @@ -99,13 +99,13 @@ private void configureClientColorimeter() { }; @Override - protected void onThresholdChange(boolean upper, float newValue) { - DestroyMessages.sendToServer(new RedstoneQuantityMonitorThresholdChangeC2SPacket(upper, newValue, colorimeter.getBlockPos())); - }; + protected void updateThresholds(float lower, float upper) { + DestroyMessages.sendToServer(new RedstoneQuantityMonitorThresholdChangeC2SPacket(lower, upper, colorimeter.getBlockPos())); + } @Override public void onClose() { - if (species != colorimeter.getMolecule() || observingGas != colorimeter.observingGas) DestroyMessages.sendToServer(new ConfigureColorimeterC2SPacket(observingGas, species, colorimeter.getBlockPos())); + DestroyMessages.sendToServer(new ConfigureColorimeterC2SPacket(observingGas, species, colorimeter.getBlockPos())); super.onClose(); }; @@ -121,7 +121,7 @@ protected void renderWindow(GuiGraphics graphics, int mX, int mY, float partialT ms.translate(guiLeft + 3, guiTop + 16, 100); GuiHelper.startStencil(graphics, 0, 0, 250, 85); MoleculeRenderer renderer = species.getRenderer(); - ms.translate((double)-renderer.getWidth() / 2d, (double)-renderer.getHeight() / 2d, 0); + ms.translate(0d, (double)-renderer.getHeight() / 2d, 0); renderer.render(125, 42, graphics); GuiHelper.endStencil(); ms.popPose(); From 7129947ed34060a5437a1b87ff9656b724c8600d Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 21:16:06 +0100 Subject: [PATCH 23/56] =?UTF-8?q?=E2=9E=95=20Possibly=20fixed=20a=20server?= =?UTF-8?q?=20freeze=20issue=20with=20the=20Vat=20and=20other=20weird=20in?= =?UTF-8?q?teractions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if i'm right about this that is one nasty typo --- .../com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java index b0b1e3076..bbcbaea2a 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java @@ -654,7 +654,7 @@ public Phases separatePhases(double initialVolume) { // Add Reaction Results to new Mixtures for (Entry entry : reactionResults.entrySet()) { double resultMoles = entry.getValue() * initialVolume; - double newTotalVolume = newLiquidVolume * newGasVolume; + double newTotalVolume = newLiquidVolume + newGasVolume; liquidMixture.reactionResults.put(entry.getKey(), (float)(resultMoles / newTotalVolume)); // A cancelled-out expression for (resultMoles / liquidVolume) * (liquidVolume / (liquidVolume + gasVolume)). Essentially we just divvy out the results based on the volumes of the two phases gasMixture.reactionResults.put(entry.getKey(), (float)(resultMoles / newTotalVolume)); }; @@ -768,7 +768,6 @@ public Map getCompletedResults(double volumeInLiters) { // Decrease the amount of Reaction that has happened reactionResults.replace(result, molesPerLiterOfReaction - numberOfResult * result.getRequiredMoles() / (float)volumeInLiters); - results.put(result, numberOfResult); }; // reactionResults.keySet().removeIf(result -> { // Remove any one-off Results and Results which have run out From a73ded61a2d81f2deb3dee800f238a5a35c65eab Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 22:58:33 +0100 Subject: [PATCH 24/56] =?UTF-8?q?=F0=9F=AB=B3=20Pick=20up,=20put=20down,?= =?UTF-8?q?=20flick=20levers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed not being able to interact with blocks while holding beakers and similar items --- .../storage/PlaceableMixtureTankItem.java | 6 +++ .../core/event/DestroyCommonEvents.java | 9 ---- .../mixin/MultiPlayerGameModeMixin.java | 47 ++++++++++++++++++ .../mixin/ServerPlayerGameModeMixin.java | 48 +++++++++++++++++++ .../mixin/plugin/DestroyMixinPlugin.java | 1 - src/main/resources/destroy.mixins.json | 4 +- 6 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/petrolpark/destroy/mixin/MultiPlayerGameModeMixin.java create mode 100644 src/main/java/com/petrolpark/destroy/mixin/ServerPlayerGameModeMixin.java diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankItem.java b/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankItem.java index 96f8e025e..c439d41cd 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankItem.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/storage/PlaceableMixtureTankItem.java @@ -51,6 +51,12 @@ public boolean canAttackBlock(BlockState state, Level level, BlockPos pos, Playe @Override public InteractionResult place(BlockPlaceContext context) { + if(context.getPlayer() != null && context.getPlayer().getAbilities().instabuild) { + context.getPlayer().getAbilities().instabuild = false; + InteractionResult res = super.place(context); + context.getPlayer().getAbilities().instabuild = true; + return res; + } return IPickUpPutDownBlock.removeItemFromInventory(context, super.place(context)); }; diff --git a/src/main/java/com/petrolpark/destroy/core/event/DestroyCommonEvents.java b/src/main/java/com/petrolpark/destroy/core/event/DestroyCommonEvents.java index 6b5926665..45861131c 100644 --- a/src/main/java/com/petrolpark/destroy/core/event/DestroyCommonEvents.java +++ b/src/main/java/com/petrolpark/destroy/core/event/DestroyCommonEvents.java @@ -480,15 +480,6 @@ public static final void onPlayerRightClickBlock(PlayerInteractEvent.RightClickB }; }; - // Consuming certain Items, even if in Creative - if (!AllBlocks.DEPLOYER.has(state) && event.getItemStack().getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof IPickUpPutDownBlock) { - InteractionResult result = stack.useOn(new UseOnContext(player, event.getHand(), event.getHitVec())); - if (result.consumesAction() && player instanceof ServerPlayer serverPlayer) CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(serverPlayer, pos, stack); - event.setCancellationResult(result); - if (result != InteractionResult.PASS) event.setCanceled(true); - return; - }; - // Fireproof Flint and Steel if (stack.getItem() == Items.FLINT_AND_STEEL && FireproofingHelper.isFireproof(player.level().registryAccess(), stack)) { DestroyAdvancementTrigger.FIREPROOF_FLINT_AND_STEEL.award(player.level(), player); diff --git a/src/main/java/com/petrolpark/destroy/mixin/MultiPlayerGameModeMixin.java b/src/main/java/com/petrolpark/destroy/mixin/MultiPlayerGameModeMixin.java new file mode 100644 index 000000000..2662321b0 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/MultiPlayerGameModeMixin.java @@ -0,0 +1,47 @@ +package com.petrolpark.destroy.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.petrolpark.destroy.core.block.IPickUpPutDownBlock; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(MultiPlayerGameMode.class) +public class MultiPlayerGameModeMixin { + private static boolean currentItemStackIgnoresCreative = false; + + @Inject( + method = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;performUseItemOn(Lnet/minecraft/client/player/LocalPlayer;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;useOn(Lnet/minecraft/world/item/context/UseOnContext;)Lnet/minecraft/world/InteractionResult;", + ordinal = 0 + ) + ) + private void checkCurrentItemStack(LocalPlayer pPlayer, InteractionHand pHand, BlockHitResult pResult, CallbackInfoReturnable cir) { + currentItemStackIgnoresCreative = pPlayer.getItemInHand(pHand).getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof IPickUpPutDownBlock; + } + + @WrapOperation( + method = "Lnet/minecraft/client/multiplayer/MultiPlayerGameMode;performUseItemOn(Lnet/minecraft/client/player/LocalPlayer;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;setCount(I)V" + ) + ) + private void dontRevertItemStack(ItemStack instance, int pCount, Operation original) { + if(currentItemStackIgnoresCreative) + currentItemStackIgnoresCreative = false; + else + original.call(instance, pCount); + } +} diff --git a/src/main/java/com/petrolpark/destroy/mixin/ServerPlayerGameModeMixin.java b/src/main/java/com/petrolpark/destroy/mixin/ServerPlayerGameModeMixin.java new file mode 100644 index 000000000..09c45eae3 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/ServerPlayerGameModeMixin.java @@ -0,0 +1,48 @@ +package com.petrolpark.destroy.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.petrolpark.destroy.core.block.IPickUpPutDownBlock; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayerGameMode; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ServerPlayerGameMode.class) +public class ServerPlayerGameModeMixin { + private static boolean currentItemStackIgnoresCreative = false; + + @Inject( + method = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItemOn(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;useOn(Lnet/minecraft/world/item/context/UseOnContext;)Lnet/minecraft/world/InteractionResult;", + ordinal = 0 + ) + ) + private void checkCurrentItemStack(ServerPlayer pPlayer, Level pLevel, ItemStack pStack, InteractionHand pHand, BlockHitResult pHitResult, CallbackInfoReturnable cir) { + currentItemStackIgnoresCreative = pStack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof IPickUpPutDownBlock; + } + + @WrapOperation( + method = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItemOn(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;setCount(I)V" + ) + ) + private void dontRevertItemStack(ItemStack instance, int pCount, Operation original) { + if(currentItemStackIgnoresCreative) + currentItemStackIgnoresCreative = false; + else + original.call(instance, pCount); + } +} diff --git a/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java b/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java index 24c712af7..a80168e6c 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/plugin/DestroyMixinPlugin.java @@ -2,7 +2,6 @@ import com.bawnorton.mixinsquared.canceller.MixinCancellerRegistrar; import com.petrolpark.compat.CompatMods; -import com.petrolpark.destroy.Destroy; import com.petrolpark.mixin.plugin.PetrolparkMixinPlugin; public class DestroyMixinPlugin extends PetrolparkMixinPlugin { diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 89a2be060..e04e0913f 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -1,5 +1,5 @@ { - "required": "true", + "required": true, "package": "com.petrolpark.destroy.mixin", "compatibilityLevel": "JAVA_17", "refmap": "destroy.refmap.json", @@ -48,6 +48,7 @@ "ItemEntityMixin", "LevelSettingsMixin", "MechanicalMixerBlockEntityMixin", + "MultiPlayerGameModeMixin", "PipeConnectionMixin", "PlayerMixin", "PonderTagScreenMixin", @@ -55,6 +56,7 @@ "SequencedAssemblyRecipeMixin", "ServerGamePacketListenerImplMixin", "ServerLevelMixin", + "ServerPlayerGameModeMixin", "SoundEntryBuilderMixin", "SplashingTypeMixin", "SpoutBlockMixin", From 6f5d08d7cb3629d54be67843534ff795fe3ab919 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 22:59:59 +0100 Subject: [PATCH 25/56] =?UTF-8?q?=F0=9F=8E=92=20Temp=20fix=20for=20Sophist?= =?UTF-8?q?icated=20Storage=20compatibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixes some code related to Creatine causing issues with upgrade slots from Sophisticated Storage containers --- .../destroy/mixin/AbstractContainerMenuMixin.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/mixin/AbstractContainerMenuMixin.java b/src/main/java/com/petrolpark/destroy/mixin/AbstractContainerMenuMixin.java index 557617e26..97fd360fb 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/AbstractContainerMenuMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/AbstractContainerMenuMixin.java @@ -22,6 +22,8 @@ public abstract class AbstractContainerMenuMixin implements DelayedSlotPopulatio @Shadow public abstract Slot getSlot(int pSlotId); @Shadow + public abstract boolean isValidSlotIndex(int pSlotIndex); + @Shadow private ItemStack carried; @Shadow private int stateId; @@ -38,7 +40,7 @@ public void populateDelayedSlots() { @Overwrite public void setItem(int pSlotId, int pStateId, ItemStack pStack) { - if (pSlotId >= slots.size()) { + if (!isValidSlotIndex(pSlotId)) { delayedSlotStacks.put(pSlotId, pStack); } else { getSlot(pSlotId).set(pStack); @@ -50,7 +52,7 @@ public void setItem(int pSlotId, int pStateId, ItemStack pStack) { public void initializeContents(int pStateId, List pItems, ItemStack pCarried) { for (int i = 0; i < pItems.size(); ++i) { ItemStack stack = pItems.get(i); - if (i >= slots.size()) { + if (!isValidSlotIndex(i)) { delayedSlotStacks.put(i, stack); } else { getSlot(i).set(stack); @@ -61,5 +63,5 @@ public void initializeContents(int pStateId, List pItems, ItemStack p }; - + }; From 5fb46c4f63a64e5b913317594357a56222863d90 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 23 Mar 2025 23:05:32 +0100 Subject: [PATCH 26/56] =?UTF-8?q?=F0=9F=A7=AA=20Fancy=20JEI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Molecules render as 3D models in JEI - Chemical reactions now display the molar ratio of every reactant and product - Fixed incorrect Borax dissolution reaction - Fixed a minor typo in the description for TATP synthesis --- .../legacy/index/DestroyReactions.java | 4 +- .../compat/jei/MoleculeJEIIngredient.java | 30 +++++++- .../jei/animation/JEIMoleculeRenderer.java | 10 --- .../compat/jei/category/ReactionCategory.java | 52 +++++++++++++- .../core/chemistry/MoleculeRenderer.java | 69 ++++++++----------- .../resources/assets/destroy/lang/en_gb.json | 2 +- .../resources/assets/destroy/lang/en_us.json | 2 +- 7 files changed, 112 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java index 6a2e89183..24c78e356 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java @@ -35,7 +35,7 @@ public class DestroyReactions { ACETYLENE_TRIMERIZATION = builder() .id("acetylene_trimerization") .addReactant(DestroyMolecules.ACETYLENE, 3) - .addSimpleItemTagCatalyst(AllTags.forgeItemTag("dusts/nickel"), 5f) + .addSimpleItemTagCatalyst(AllTags.forgeItemTag("dusts/nickel"), 1f) .addProduct(DestroyMolecules.BENZENE) .build(), @@ -125,7 +125,7 @@ public class DestroyReactions { BORAX_DISSOLUTION = builder() .id("borax_dissolution") .addReactant(DestroyMolecules.PROTON, 2, 1) - .addSimpleItemTagCatalyst(AllTags.forgeItemTag("raw_materials/borax"), 16f) + .addSimpleItemTagReactant(AllTags.forgeItemTag("raw_materials/borax"), 15f) .addCatalyst(DestroyMolecules.CHLORIDE, 1) .addProduct(DestroyMolecules.SODIUM_ION, 2) .addProduct(DestroyMolecules.WATER, 5) diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java index 3c293de07..56d24ef6b 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java @@ -4,6 +4,7 @@ import javax.annotation.Nullable; +import com.mojang.blaze3d.vertex.PoseStack; import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.DestroyFluids; import com.petrolpark.destroy.DestroyItems; @@ -15,6 +16,7 @@ import com.petrolpark.destroy.config.DestroyAllConfigs; import com.petrolpark.destroy.core.chemistry.MoleculeDisplayItem; import com.petrolpark.destroy.core.chemistry.MoleculeDisplayItem.MoleculeTooltip; +import com.petrolpark.destroy.core.chemistry.MoleculeRenderer; import com.petrolpark.destroy.core.chemistry.storage.testtube.TestTubeItem; import mezz.jei.api.gui.builder.ITooltipBuilder; @@ -22,6 +24,8 @@ import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.ingredients.subtypes.UidContext; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -105,7 +109,31 @@ public ItemStack getCheatItemStack(LegacySpecies ingredient) { @Override public void render(GuiGraphics graphics, LegacySpecies ingredient) { - graphics.renderItem(MoleculeDisplayItem.with(ingredient), 0, 0); // TODO check positioning + MoleculeRenderer renderer = ingredient.getRenderer(); + + PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + renderer.renderItem(0, 0, 16, 16, graphics); + + if(ingredient.getCharge() != 0) + { + String s = ingredient.getCharge() > 0 ? "+" : "-"; + int col = 0xFFFFFF; + + if(Math.abs(ingredient.getCharge()) > 1) + s = Math.abs(ingredient.getCharge()) + s; + + poseStack.pushPose(); + poseStack.translate(0, 0, 100); + poseStack.scale(0.5f, 0.5f, 0.5f); + Font fontRenderer = Minecraft.getInstance().font; + graphics.drawString(fontRenderer, s, -1, -1, col, true); + poseStack.popPose(); + } + + poseStack.popPose(); + + //graphics.renderItem(MoleculeDisplayItem.with(ingredient), 0, 0); // TODO check positioning }; @Override diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/animation/JEIMoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/compat/jei/animation/JEIMoleculeRenderer.java index 283d1bafe..958eb42d9 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/animation/JEIMoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/animation/JEIMoleculeRenderer.java @@ -12,16 +12,6 @@ public JEIMoleculeRenderer(LegacySpecies molecule) { super(molecule); }; - @Override - public int getWidth() { - return width; - }; - - @Override - public int getHeight() { - return height; - }; - @Override public void draw(GuiGraphics graphics, int xOffset, int yOffset) { render(xOffset, yOffset, graphics); diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java b/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java index 298bff3ba..ca3bd688e 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java @@ -7,6 +7,11 @@ import java.util.List; import java.util.Map; +import com.ibm.icu.text.DecimalFormat; +import mezz.jei.api.gui.drawable.IDrawable; +import net.minecraft.client.gui.Font; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import org.joml.Vector2i; import com.petrolpark.client.rendering.PetrolparkGuiTexture; @@ -113,11 +118,21 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse int numberOfReactants = getNumberOfReactants(reaction); if (numberOfReactants >= 6) tooManyMoleculesWarning(true, reaction); + float molesPerItem = reaction.getMolesPerItem(); + if(molesPerItem == 0f) molesPerItem = 1f; + + Collection precipitates = reaction.hasResult() ? reaction.getResult().getAllPrecipitates() : Collections.emptyList(); + for (PrecipitateReactionResult precipitate : precipitates) { + molesPerItem = precipitate.getRequiredMoles(); + } + + for (LegacySpecies reactant : reaction.getReactants()) { if (i >= 6) continue; Vector2i pos = getReactantRenderPosition(i, numberOfReactants); builder.addSlot(RecipeIngredientRole.INPUT, pos.x, pos.y) .addIngredient(MoleculeJEIIngredient.TYPE, reactant) + .setOverlay(createOverlay(reaction.getReactantMolarRatio(reactant) * molesPerItem), 0, 0) .addRichTooltipCallback(ReactionTooltipHelper.reactantTooltip(reaction, reactant)) .setBackground(getRenderedSlot(), -1, -1); i++; @@ -135,8 +150,6 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse }; }; - Collection precipitates = reaction.hasResult() ? reaction.getResult().getAllPrecipitates() : Collections.emptyList(); - int j = 0; int numberOfProducts = reaction.getProducts().size() + precipitates.size(); @@ -157,6 +170,7 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse if (j >= 6) continue; builder.addSlot(RecipeIngredientRole.OUTPUT, productsXOffset + (19 * (j % l)), productYOffset + (j / l) * 19) .addIngredient(MoleculeJEIIngredient.TYPE, product) + .setOverlay(createOverlay(reaction.getProductMolarRatio(product) * molesPerItem), 0, 0) .addRichTooltipCallback(ReactionTooltipHelper.productTooltip(reaction, product)) .setBackground(getRenderedSlot(), -1, -1); j++; @@ -253,5 +267,37 @@ public void draw(T recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphic PetrolparkGuiTexture.JEI_LINE.render(graphics, 2, 85); (recipe.getReaction().displayAsReversible() ? PetrolparkGuiTexture.JEI_EQUILIBRIUM_ARROW : AllGuiTextures.JEI_ARROW).render(graphics, yOffset + 37, 46); }; - + + private static DecimalFormat df = new DecimalFormat("#.#"); + + public IDrawable createOverlay(float molarRatio) { + String s = molarRatio == 1f ? "" : df.format(molarRatio); + float scale = s.length() > 2 ? 0.75f : 1f; + + return new IDrawable() { + + @Override + public int getWidth() {return 16;} + + @Override + public int getHeight() {return 16;} + + @Override + public void draw(GuiGraphics graphics, int xOffset, int yOffset) { + if(s.isEmpty()) return; + + graphics.pose().pushPose(); + graphics.pose().translate(0, 0, 0); + graphics.pose().scale(scale, scale, 1); + + Font fontRenderer = Minecraft.getInstance().font; + graphics.drawString(fontRenderer, s, + (xOffset + getWidth()) / scale - fontRenderer.width(s) + 1, + (yOffset + getHeight()) / scale - 7, + 0xFFFFFF, true); + + graphics.pose().popPose(); + } + }; + } }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index d1bf4e0a6..e0aea9e2b 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.Map.Entry; +import com.mojang.math.Axis; +import net.minecraft.world.phys.AABB; import org.joml.Math; import org.joml.Quaternionf; @@ -33,26 +35,7 @@ public class MoleculeRenderer { protected String moleculeID; - /** - * The distance from 0 to the highest X value of any rendered object. - */ - protected int width; - /** - * The distance from 0 to the highest Y value of any rendered object. - */ - protected int height; - /** - * How far below X = 0 this rendered Molecule extends. - */ - protected int xOffset; - /** - * How far above Y = 0 this rendered Molecule extends (remember positive Y is down). - */ - protected int yOffset; - /** - * How far behind Z = 0 this rendered Molecule extends - */ - protected int zOffset; + protected AABB bb; protected static final double SCALE = 23d; protected static final double BOND_LENGTH = SCALE / 2; @@ -65,11 +48,7 @@ public class MoleculeRenderer { public MoleculeRenderer(LegacySpecies molecule) { moleculeID = molecule.getFullID(); - width = 0; - height = 0; - xOffset = 5; - yOffset = 0; - zOffset = 0; + bb = new AABB(Vec3.ZERO, Vec3.ZERO); RENDERED_OBJECTS = new ArrayList<>(); // Monatomic Molecules @@ -132,23 +111,16 @@ public MoleculeRenderer(LegacySpecies molecule) { // Rescale the Renderer to fit every Atom for (Pair pair : RENDERED_OBJECTS) { - width = Math.max(width, (int)pair.getFirst().x); - height = Math.max(height, (int)pair.getFirst().y); - // Set the X and Y offsets to the positive of the most negative respective coordinate of any rendered object present - xOffset = -(int)Math.min(-xOffset, pair.getFirst().x); - yOffset = -(int)Math.min(-yOffset, pair.getFirst().y); - zOffset = -(int)Math.min(-zOffset, pair.getFirst().z); + bb = bb.minmax(new AABB(pair.getFirst(), pair.getFirst())); }; - width += xOffset; - height += yOffset; }; public int getWidth() { - return width; + return (int)bb.getXsize(); }; public int getHeight() { - return height; + return (int)bb.getYsize(); }; /** @@ -157,10 +129,29 @@ public int getHeight() { public void render(int xPosition, int yPosition, GuiGraphics graphics) { PoseStack poseStack = graphics.pose(); poseStack.pushPose(); - poseStack.translate(xPosition + ((float)width / 2f), yPosition + yOffset, -200); - TransformStack.cast(poseStack) - .rotateY(AnimationTickHolder.getRenderTime()); // Rotation - poseStack.translate(-((float)width) / 2f + xOffset, 0f, 0f); + Vec3 center = bb.getCenter(); + poseStack.translate(center.x - bb.minX + xPosition, center.y - bb.minY + yPosition, -200); + poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); + poseStack.translate(-center.x, -center.y, -center.z); + + for (Pair pair : RENDERED_OBJECTS) { + pair.getSecond().render(graphics, pair.getFirst()); + }; + poseStack.popPose(); + }; + + public void renderItem(int xPosition, int yPosition, int width, int height, GuiGraphics graphics) { + float scale = java.lang.Math.min(0.5f, java.lang.Math.min((width+2)/(getWidth()+1f), (height+2)/(getHeight()+1f))); + + PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + Vec3 center = bb.getCenter(); + poseStack.translate(xPosition + width/2, yPosition + height/2, 50); + poseStack.mulPose(Axis.XP.rotationDegrees(-10)); + poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); + poseStack.scale(scale, scale, scale); + poseStack.translate(-center.x, -center.y, -center.z); + for (Pair pair : RENDERED_OBJECTS) { pair.getSecond().render(graphics, pair.getFirst()); }; diff --git a/src/main/resources/assets/destroy/lang/en_gb.json b/src/main/resources/assets/destroy/lang/en_gb.json index 065d13f73..88725fa29 100644 --- a/src/main/resources/assets/destroy/lang/en_gb.json +++ b/src/main/resources/assets/destroy/lang/en_gb.json @@ -1390,7 +1390,7 @@ "destroy.reaction.sulfur_trioxide_hydration": "[destroy:sulfur_trioxide] Hydration", "destroy.reaction.sulfur_trioxide_hydration.description": "The {hydration, destroy:hydrolysis} of [destroy:sulfur_trioxide] to make [destroy:sulfuric_acid], which is the ultimate product from combining [destroy:sulfur], [destroy:oxygen] and [destroy:water].", "destroy.reaction.tatp": "Acetone Peroxide Synthesis", - "destroy.reaction.tatp.description": "A dangerous way of producing an explosive, which has injured many an amatuer chemist.", + "destroy.reaction.tatp.description": "A dangerous way of producing an explosive, which has injured many an amateur chemist.", "destroy.reaction.tetraborate_equilibrium": "[destroy:tetrahydroxy_tetraborate] Equilibrium", "destroy.reaction.tetraborate_equilibrium.description": "The interconversion of various boron oxides in solution.", "destroy.reaction.tetraethyllead_synthesis": "[destroy:tetraethyllead] Synthesis", diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index beac5953c..bf10ad918 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -1270,7 +1270,7 @@ "destroy.reaction.sulfur_trioxide_hydration": "[destroy:sulfur_trioxide] Hydration", "destroy.reaction.sulfur_trioxide_hydration.description": "The {hydration, destroy:hydrolysis} of [destroy:sulfur_trioxide] to make [destroy:sulfuric_acid], which is the ultimate product from combining [destroy:sulfur], [destroy:oxygen] and [destroy:water].", "destroy.reaction.tatp": "Acetone Peroxide Synthesis", - "destroy.reaction.tatp.description": "A dangerous way of producing an explosive, which has injured many an amatuer chemist.", + "destroy.reaction.tatp.description": "A dangerous way of producing an explosive, which has injured many an amateur chemist.", "destroy.reaction.tetraborate_equilibrium": "[destroy:tetrahydroxy_tetraborate] Equilibrium", "destroy.reaction.tetraborate_equilibrium.description": "The interconversion of various boron oxides in solution.", "destroy.reaction.tetraethyllead_synthesis": "[destroy:tetraethyllead] Synthesis", From 11dfef796fba3a01c65f515afe7f529d006544bd Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 24 Mar 2025 00:11:35 +0100 Subject: [PATCH 27/56] =?UTF-8?q?=F0=9F=A5=9B=20Stacking=20tubes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Test tubes, beakers and other mixture containers now clear their NBT data when completely emptied (this allows them to be considered identical and therefore stack in AE2 networks or Sophisticated Storage containers) --- .../destroy/core/fluid/GeniusFluidTankBehaviour.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/petrolpark/destroy/core/fluid/GeniusFluidTankBehaviour.java b/src/main/java/com/petrolpark/destroy/core/fluid/GeniusFluidTankBehaviour.java index 9903694c5..5b592bba7 100644 --- a/src/main/java/com/petrolpark/destroy/core/fluid/GeniusFluidTankBehaviour.java +++ b/src/main/java/com/petrolpark/destroy/core/fluid/GeniusFluidTankBehaviour.java @@ -12,6 +12,7 @@ import com.simibubi.create.foundation.fluid.SmartFluidTank; import net.minecraft.nbt.Tag; +import net.minecraft.world.level.material.Fluids; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -87,6 +88,17 @@ public int fill(FluidStack resource, FluidAction action) { return filled; }; + @Override + public FluidStack drain(int maxDrain, FluidAction action) + { + FluidStack stack = super.drain(maxDrain, action); + // Replace the held fluid with an empty fluid stack if we completely emptied this tank + // This clears mixture data and allows empty containers of the same type to stack + if(fluid.isEmpty() && fluid.getRawFluid() != Fluids.EMPTY) + setFluid(FluidStack.EMPTY); + return stack; + } + }; }; From 22a47f045ac71b04bba41aaa1e931e40e2734ea3 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 24 Mar 2025 21:02:19 +0100 Subject: [PATCH 28/56] =?UTF-8?q?=E2=9A=BE=20Misplaced=20balls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed some example molecules rendering incorrectly in organic reactions (e.g. Alkene Hydrochlorination) - Fixed displayed result of Cyanamide Addition missing hydrogen atoms - Fixed Cyanamide Ion Hydrolysis requiring one too many moles of water --- .../destroy/chemistry/legacy/LegacyMolecularStructure.java | 7 +++++-- .../destroy/chemistry/legacy/index/DestroyReactions.java | 2 +- .../legacy/index/genericreaction/CyanamideAddition.java | 4 ++++ .../observation/colorimeter/ColorimeterBlockEntity.java | 1 - 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java index de6be89a8..a0f573d3a 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java @@ -797,9 +797,12 @@ private static Branch getMaximumBranchWithHighestMass(Map { return getMaximumBranch(a2, structure).getMassOfLongestChain().compareTo(getMaximumBranch(a1, structure).getMassOfLongestChain()); // Put in descending order of chain length }); - Collections.sort(terminalAtoms, (a1, a2) -> { + + // Commenting this out since this seems to break rendering with numbered R groups + // Not entirely sure what this does since getMassOfLongestChain should already take care of sorting R groups by index + /*Collections.sort(terminalAtoms, (a1, a2) -> { return Branch.getMassForComparisonInSerialization(a1).compareTo(Branch.getMassForComparisonInSerialization(a2)); - }); + });*/ return getMaximumBranch(terminalAtoms.get(0), structure); }; diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java index 24c78e356..6558718e6 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyReactions.java @@ -342,7 +342,7 @@ public class DestroyReactions { CYANAMIDE_ION_HYDROLYSIS = builder() .id("cyanamide_ion_hydrolysis") .addReactant(DestroyMolecules.CYANAMIDE_ION) - .addReactant(DestroyMolecules.WATER, 3, 1) + .addReactant(DestroyMolecules.WATER, 2, 1) .addProduct(DestroyMolecules.CYANAMIDE) .addProduct(DestroyMolecules.HYDROXIDE, 2) .build(), diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/genericreaction/CyanamideAddition.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/genericreaction/CyanamideAddition.java index 46034292f..dd62fc388 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/genericreaction/CyanamideAddition.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/genericreaction/CyanamideAddition.java @@ -31,6 +31,10 @@ public LegacyReaction generateReaction(GenericReactant re .addGroup(LegacyMolecularStructure.atom(LegacyElement.CARBON), false) .addAtom(LegacyElement.NITROGEN) .addAtom(LegacyElement.NITROGEN, BondType.DOUBLE); + + if(reactant.molecule.isHypothetical()) + structure.addAllHydrogens(); + return reactionBuilder() .addReactant(reactant.molecule) .addReactant(DestroyMolecules.CYANAMIDE) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java index b17a7c14c..42e28f640 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterBlockEntity.java @@ -132,7 +132,6 @@ public void onNeighborChanged(BlockPos neighborPos) { public void updateVat() { Optional vat = getVatOptional(); - Destroy.LOGGER.info("updated vat {}", vat); if (molecule != null && vat.isPresent()) { redstoneMonitor.quantityObserved = Optional.of(() -> { FluidStack mixtureStack = (observingGas ? vat.get().getGasTankContents() : vat.get().getLiquidTankContents()); From 54f640e4e32e4ddbec2327d667e94aac0b9e92de Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Tue, 25 Mar 2025 01:46:41 +0100 Subject: [PATCH 29/56] =?UTF-8?q?=F0=9F=92=80=20Should've=20tested=20this?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed Swiss Army Knife causing dedicated servers to crash on startup --- .../tool/swissarmyknife/SwissArmyKnifeItem.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java index 370d425c0..a07e0af1d 100644 --- a/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java +++ b/src/main/java/com/petrolpark/destroy/content/tool/swissarmyknife/SwissArmyKnifeItem.java @@ -57,6 +57,8 @@ public SwissArmyKnifeItem(float attackDamageModifier, float attackSpeedModifier, @OnlyIn(Dist.CLIENT) public static class ClientState { + private static Map states = new WeakHashMap<>(); + @Nullable public Tool selectedTool = null; public Tool lastSelectedTool = null; @@ -86,8 +88,6 @@ public void tick() { }; @OnlyIn(Dist.CLIENT) - private static Map clientStates = new WeakHashMap<>(); - @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { if (level.isClientSide() && entity == Minecraft.getInstance().player) { @@ -162,8 +162,8 @@ public void initializeClient(Consumer consumer) { public static void clientPlayerTick() { Minecraft minecraft = Minecraft.getInstance(); - clientStates.keySet().removeIf(entity -> !(entity.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem || entity.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)); - clientStates.forEach((entity, state) -> state.tick()); + ClientState.states.keySet().removeIf(entity -> !(entity.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof SwissArmyKnifeItem || entity.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof SwissArmyKnifeItem)); + ClientState.states.forEach((entity, state) -> state.tick()); LocalPlayer player = minecraft.player; if (player == null) return; @@ -233,8 +233,9 @@ public static void putTool(ItemStack stack, @Nullable Tool tool) { if (tool != null) stack.getOrCreateTag().putInt("ActiveTool", tool.ordinal()); }; + @OnlyIn(Dist.CLIENT) public static ClientState getClientState(LivingEntity entity) { - return clientStates.computeIfAbsent(entity, e -> new ClientState()); + return ClientState.states.computeIfAbsent(entity, e -> new ClientState()); }; public static enum Tool { From b33d1296ffc73925805f41239289e710f7909871 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Wed, 26 Mar 2025 16:08:51 +0100 Subject: [PATCH 30/56] =?UTF-8?q?=E2=9B=9B=20This=20is=20giving=20me=20a?= =?UTF-8?q?=20tetraheadache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed side branches using the wrong geometry (this was the actual cause for terminal atoms clipping backwards) - Replaced HashMap with LinkedHashMap in LegacyMolecularStructure to ensure 3d representations of molecules are generated in a deterministic order --- .../legacy/LegacyMolecularStructure.java | 20 ++++++------------- .../core/chemistry/MoleculeRenderer.java | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java index a0f573d3a..6fbd20260 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java @@ -1,14 +1,6 @@ package com.petrolpark.destroy.chemistry.legacy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.Map.Entry; import javax.annotation.Nullable; @@ -85,7 +77,7 @@ public class LegacyMolecularStructure implements Cloneable { private String optimumFROWNSCode; private LegacyMolecularStructure() { - structure = new HashMap>(); + structure = new LinkedHashMap>(); groups = new ArrayList<>(); topology = Topology.LINEAR; sideChains = new ArrayList<>(); @@ -606,7 +598,7 @@ public LegacyMolecularStructure addCarbonyl() { * @return This Formula */ public LegacyMolecularStructure addAllHydrogens() { - Map> newStructure = new HashMap>(structure); // Create a shallow copy, as the original structure can't be modified while being iterated over + Map> newStructure = new LinkedHashMap>(structure); // Create a shallow copy, as the original structure can't be modified while being iterated over // Replace all empty side chains with Hydrogen, if necessary if (topology != Topology.LINEAR) { @@ -888,7 +880,7 @@ public LegacyMolecularStructure shallowCopy() { try { LegacyMolecularStructure newFormula = (LegacyMolecularStructure) super.clone(); - newFormula.structure = new HashMap<>(structure.size()); + newFormula.structure = new LinkedHashMap<>(structure.size()); newFormula.structure = shallowCopyStructure(structure); // Shallow copy the Structure newFormula.groups = new ArrayList<>(groups); // Shallow copy the Groups newFormula.topology = this.topology; // Shallow copy the Topology @@ -933,7 +925,7 @@ public Branch getRenderBranch() { * @see LegacyMolecularStructure#shallowCopy The wrapper for this Method */ private static Map> shallowCopyStructure(Map> structureToCopy) { - Map> newStructure = new HashMap<>(); + Map> newStructure = new LinkedHashMap<>(); for (LegacyAtom atom : structureToCopy.keySet()) { List oldBonds = structureToCopy.get(atom); List newBonds = new ArrayList<>(); @@ -1197,7 +1189,7 @@ private static BondType trailingBondType(String symbol) { * @return The original structure, now with its non-acidic hydrogen Atoms removed */ private static Map> stripHydrogens(Map> structure) { - Map> newStructure = new HashMap<>(); + Map> newStructure = new LinkedHashMap<>(); for (Entry> entry : structure.entrySet()) { LegacyAtom atom = entry.getKey(); List bondsToInclude = new ArrayList<>(); diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index e0aea9e2b..df1d38970 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -205,7 +205,7 @@ public void generateBranch(Branch branch, Vec3 startLocation, Vec3 direction, Ve Branch sideBranch = sideBranchAndBondType.getKey(); Vec3 newPlane = confinedGeometry.getZig().cross(sideZag); RENDERED_OBJECTS.add(Pair.of(location.add(sideZag.scale(0.5d * BOND_LENGTH)), BondRenderInstance.fromZig(sideBranchAndBondType.getValue(), sideZag))); - generateBranch(sideBranch, location.add(sideZag.scale(BOND_LENGTH)), MathsHelper.rotate(sideZag, newPlane, 90d), newPlane, sideZag, false); + generateBranch(sideBranch, location.add(sideZag.scale(BOND_LENGTH)), MathsHelper.rotate(sideZag, newPlane, 90d), newPlane, sideZag, true); j++; }; From bb49d5260551e561e270dd7d35612c675f25af4c Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 01:47:54 +0100 Subject: [PATCH 31/56] =?UTF-8?q?=F0=9F=8D=9E=20Baking=20molecules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Optimized molecule rendering in JEI (hopefully) --- .../core/chemistry/MoleculeRenderer.java | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index df1d38970..bfa697648 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -7,7 +7,17 @@ import java.util.Map; import java.util.Map.Entry; +import com.jozufozu.flywheel.core.model.ModelUtil; +import com.mojang.blaze3d.vertex.*; import com.mojang.math.Axis; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.AABB; import org.joml.Math; import org.joml.Quaternionf; @@ -15,7 +25,6 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; import com.petrolpark.destroy.chemistry.legacy.LegacyAtom; import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; import com.petrolpark.destroy.chemistry.legacy.LegacyBond.BondType; @@ -40,6 +49,8 @@ public class MoleculeRenderer { protected static final double SCALE = 23d; protected static final double BOND_LENGTH = SCALE / 2; + protected SuperByteBuffer model; + /** * The list of Atoms and Bonds to render, and their locations. * This is ordered from back to front. @@ -113,6 +124,17 @@ public MoleculeRenderer(LegacySpecies molecule) { for (Pair pair : RENDERED_OBJECTS) { bb = bb.minmax(new AABB(pair.getFirst(), pair.getFirst())); }; + + // Bake all rendered objects into a single buffer + BufferBuilder builder = new BufferBuilder(512); + builder.begin(VertexFormat.Mode.QUADS, RenderType.translucent().format()); + for (Pair pair : RENDERED_OBJECTS) { + pair.getSecond().renderInto(builder, pair.getFirst()); + }; + + BufferBuilder.RenderedBuffer renderedBuffer = builder.end(); + model = new SuperByteBuffer(renderedBuffer.vertexBuffer(), renderedBuffer.drawState()); + renderedBuffer.release(); }; public int getWidth() { @@ -133,10 +155,18 @@ public void render(int xPosition, int yPosition, GuiGraphics graphics) { poseStack.translate(center.x - bb.minX + xPosition, center.y - bb.minY + yPosition, -200); poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); poseStack.translate(-center.x, -center.y, -center.z); - +/* for (Pair pair : RENDERED_OBJECTS) { pair.getSecond().render(graphics, pair.getFirst()); }; +*/ + Minecraft mc = Minecraft.getInstance(); + MultiBufferSource.BufferSource buffer = mc.renderBuffers() + .bufferSource(); + RenderType renderType = RenderType.translucent(); + UIRenderHelper.flipForGuiRender(poseStack); + model.renderInto(poseStack, buffer.getBuffer(renderType)); + poseStack.popPose(); }; @@ -152,9 +182,19 @@ public void renderItem(int xPosition, int yPosition, int width, int height, GuiG poseStack.scale(scale, scale, scale); poseStack.translate(-center.x, -center.y, -center.z); +/* for (Pair pair : RENDERED_OBJECTS) { pair.getSecond().render(graphics, pair.getFirst()); }; +*/ + + Minecraft mc = Minecraft.getInstance(); + MultiBufferSource.BufferSource buffer = mc.renderBuffers() + .bufferSource(); + RenderType renderType = RenderType.solid(); + UIRenderHelper.flipForGuiRender(poseStack); + model.renderInto(poseStack, buffer.getBuffer(renderType)); + poseStack.popPose(); }; @@ -348,6 +388,7 @@ public static double distanceFromPointToLine(Vec3 point, Vec3 linePoint, Vec3 li protected static interface IRenderableMoleculePart { public void render(GuiGraphics graphics, Vec3 location); + public void renderInto(VertexConsumer builder, Vec3 location); }; protected static record BondRenderInstance(BondType type, Quaternionf rotation) implements IRenderableMoleculePart { @@ -379,6 +420,25 @@ public void render(GuiGraphics graphics, Vec3 location) { .render(graphics, 0, 0); poseStack.popPose(); }; + + @Override + public void renderInto(VertexConsumer builder, Vec3 location) { + PoseStack poseStack = new PoseStack(); + + // Models need to be flipped on the Y axis when rendered in the GUI in order to appear upright + // Molecules were originally rendered piece by piece, with each piece being flipped individually + // Now that molecules are baked into a single model, the Y coordinates need to be flipped so each + // piece appears in the correct position once the entire model is flipped again + poseStack.translate(location.x, -location.y, location.z); + TransformStack.cast(poseStack) + .rotateCentered(new Quaternionf(-rotation.x, rotation.y, -rotation.z, rotation.w)); // flip rotation around Y axis + + poseStack.scale((float)SCALE, (float)SCALE, (float)SCALE); + + Minecraft.getInstance().getBlockRenderer().getModelRenderer() + .renderModel(poseStack.last(), builder, Blocks.AIR.defaultBlockState(), type().getPartial().get(), 1, 1, 1, + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, null); + }; }; protected static record AtomRenderInstance(LegacyAtom atom) implements IRenderableMoleculePart { @@ -394,5 +454,17 @@ public void render(GuiGraphics graphics, Vec3 location) { .render(graphics, 0, 0); poseStack.popPose(); }; + + @Override + public void renderInto(VertexConsumer builder, Vec3 location) { + PoseStack poseStack = new PoseStack(); + + poseStack.translate(location.x, -location.y, location.z); + poseStack.scale((float)SCALE, (float)SCALE, (float)SCALE); + + Minecraft.getInstance().getBlockRenderer().getModelRenderer() + .renderModel(poseStack.last(), builder, Blocks.AIR.defaultBlockState(), atom.getPartial().get(), 1, 1, 1, + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, null); + }; }; }; From 47a0103684e03eae22da86136a0f5911b76384d5 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 02:57:33 +0100 Subject: [PATCH 32/56] =?UTF-8?q?=E2=A4=B5=EF=B8=8F=20Bad=20rotation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed bonds in 3d molecules rendering with a slight offset at certain angles --- .../petrolpark/destroy/core/chemistry/MoleculeRenderer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index bfa697648..b488d5f02 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -181,13 +181,11 @@ public void renderItem(int xPosition, int yPosition, int width, int height, GuiG poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); poseStack.scale(scale, scale, scale); poseStack.translate(-center.x, -center.y, -center.z); - /* for (Pair pair : RENDERED_OBJECTS) { pair.getSecond().render(graphics, pair.getFirst()); }; */ - Minecraft mc = Minecraft.getInstance(); MultiBufferSource.BufferSource buffer = mc.renderBuffers() .bufferSource(); @@ -431,8 +429,7 @@ public void renderInto(VertexConsumer builder, Vec3 location) { // piece appears in the correct position once the entire model is flipped again poseStack.translate(location.x, -location.y, location.z); TransformStack.cast(poseStack) - .rotateCentered(new Quaternionf(-rotation.x, rotation.y, -rotation.z, rotation.w)); // flip rotation around Y axis - + .multiply(new Quaternionf(-rotation.x, rotation.y, -rotation.z, rotation.w)); // flip rotation around Y axis poseStack.scale((float)SCALE, (float)SCALE, (float)SCALE); Minecraft.getInstance().getBlockRenderer().getModelRenderer() From da8f4382db41f544cc3c9b5821a97fb780dc1d81 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 18:59:39 +0100 Subject: [PATCH 33/56] =?UTF-8?q?=F0=9F=93=8B=20More=20JEI=20tweaks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reactions display reactants and products sorted by mass rather than in a random order, hypothetical species always come first - Added a smaller pixel font for ion charge numbers --- .../legacy/LegacyMolecularStructure.java | 6 ++-- .../compat/jei/MoleculeJEIIngredient.java | 8 +++-- .../compat/jei/category/ReactionCategory.java | 28 ++++++++++-------- .../resources/assets/destroy/font/charge.json | 10 +++++++ .../assets/destroy/textures/font/charge.png | Bin 0 -> 790 bytes 5 files changed, 33 insertions(+), 19 deletions(-) create mode 100644 src/main/resources/assets/destroy/font/charge.json create mode 100644 src/main/resources/assets/destroy/textures/font/charge.png diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java index 6fbd20260..b772d0434 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMolecularStructure.java @@ -790,11 +790,9 @@ private static Branch getMaximumBranchWithHighestMass(Map { + Collections.sort(terminalAtoms, (a1, a2) -> { return Branch.getMassForComparisonInSerialization(a1).compareTo(Branch.getMassForComparisonInSerialization(a2)); - });*/ + }); return getMaximumBranch(terminalAtoms.get(0), structure); }; diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java index 56d24ef6b..f51e1325a 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java @@ -28,7 +28,9 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.TooltipFlag; @@ -107,6 +109,9 @@ public ItemStack getCheatItemStack(LegacySpecies ingredient) { public static final IIngredientRenderer RENDERER = new IIngredientRenderer() { + public static final ResourceLocation FONT_LOCATION = Destroy.asResource("charge"); + public static final Style FONT = Style.EMPTY.withFont(FONT_LOCATION); + @Override public void render(GuiGraphics graphics, LegacySpecies ingredient) { MoleculeRenderer renderer = ingredient.getRenderer(); @@ -125,9 +130,8 @@ public void render(GuiGraphics graphics, LegacySpecies ingredient) { poseStack.pushPose(); poseStack.translate(0, 0, 100); - poseStack.scale(0.5f, 0.5f, 0.5f); Font fontRenderer = Minecraft.getInstance().font; - graphics.drawString(fontRenderer, s, -1, -1, col, true); + graphics.drawString(fontRenderer, FormattedCharSequence.forward(s, FONT), -1, -1, col, true); poseStack.popPose(); } diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java b/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java index ca3bd688e..79a09c1de 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/category/ReactionCategory.java @@ -1,13 +1,9 @@ package com.petrolpark.destroy.compat.jei.category; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import com.ibm.icu.text.DecimalFormat; +import com.petrolpark.destroy.chemistry.legacy.*; import mezz.jei.api.gui.drawable.IDrawable; import net.minecraft.client.gui.Font; import net.minecraftforge.api.distmarker.Dist; @@ -18,9 +14,6 @@ import com.petrolpark.compat.jei.JEITextureDrawable; import com.petrolpark.destroy.Destroy; import com.petrolpark.destroy.DestroyItems; -import com.petrolpark.destroy.chemistry.legacy.IItemReactant; -import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; -import com.petrolpark.destroy.chemistry.legacy.LegacyReaction; import com.petrolpark.destroy.chemistry.legacy.reactionresult.PrecipitateReactionResult; import com.petrolpark.destroy.client.DestroyLang; import com.petrolpark.destroy.client.stackedtextbox.AbstractStackedTextBox; @@ -108,6 +101,16 @@ private static void tooManyMoleculesWarning(boolean reactants, LegacyReaction re Destroy.LOGGER.warn("Reaction '"+reaction.getFullId()+"' has too many " + (reactants ? "reactants" : "products") + " to fit on JEI."); }; + public static float getSpeciesWeightForSorting(LegacySpecies s) { + LegacyAtom atom = Collections.max(s.getAtoms(), Comparator.comparing(a -> a.getElement() == LegacyElement.R_GROUP ? a.rGroupNumber : -1)); + float weight = -s.getMass(); + + if(atom.getElement() == LegacyElement.R_GROUP) + weight -= 1000f - 100f * atom.rGroupNumber; + + return weight; + } + @Override public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuses) { super.setRecipe(builder, recipe, focuses); @@ -126,8 +129,7 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse molesPerItem = precipitate.getRequiredMoles(); } - - for (LegacySpecies reactant : reaction.getReactants()) { + for (LegacySpecies reactant : reaction.getReactants().stream().sorted(Comparator.comparing(ReactionCategory::getSpeciesWeightForSorting)).toList()) { if (i >= 6) continue; Vector2i pos = getReactantRenderPosition(i, numberOfReactants); builder.addSlot(RecipeIngredientRole.INPUT, pos.x, pos.y) @@ -166,7 +168,7 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse int l = numberOfProducts == 4 ? 2 : 3; - for (LegacySpecies product : reaction.getProducts()) { + for (LegacySpecies product : reaction.getProducts().stream().sorted(Comparator.comparing(ReactionCategory::getSpeciesWeightForSorting)).toList()) { if (j >= 6) continue; builder.addSlot(RecipeIngredientRole.OUTPUT, productsXOffset + (19 * (j % l)), productYOffset + (j / l) * 19) .addIngredient(MoleculeJEIIngredient.TYPE, product) @@ -189,7 +191,7 @@ public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuse int m = 0; if (reaction.needsUV()) m++; // If there is UV catalyst, this is already drawn - for (LegacySpecies catalyst : reaction.getOrders().keySet()) { + for (LegacySpecies catalyst : reaction.getOrders().keySet().stream().sorted(Comparator.comparing(ReactionCategory::getSpeciesWeightForSorting)).toList()) { if (reaction.getReactants().contains(catalyst)) continue; Vector2i pos = getCatalystRenderPosition(m, numberOfCatalysts); builder.addSlot(RecipeIngredientRole.CATALYST, pos.x, pos.y) diff --git a/src/main/resources/assets/destroy/font/charge.json b/src/main/resources/assets/destroy/font/charge.json new file mode 100644 index 000000000..a984cc670 --- /dev/null +++ b/src/main/resources/assets/destroy/font/charge.json @@ -0,0 +1,10 @@ +{ + "providers": [ + { + "type": "bitmap", + "file": "destroy:font/charge.png", + "ascent": 7, + "chars": ["0123456789+-"] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/destroy/textures/font/charge.png b/src/main/resources/assets/destroy/textures/font/charge.png new file mode 100644 index 0000000000000000000000000000000000000000..e8354fe5b025e91f3946381af85b6b2fa8b2f89f GIT binary patch literal 790 zcmeAS@N?(olHy`uVBq!ia0vp^20+Zg!3HGvYuC6lFfcY{Iy(n=Iy)-_6y>L7=A<$( zXq=xq(b9w2QKEJK5n+B7--SsVTca`;D@_w}6%u`Vg?wHJkyDfJ+dY2|>M^u=^ zwf1h^Cbq3fp`sxoIzsbS$D02+Ei8&n%!h0C%=|v1lKEhBPv*|4hZAmAsvF5&ODg^x zb=LUmmOy{w++8o9ElWGLXo{@-c9ttumsfB4aX+I+f43To$-_kB=TBOvx3GtQwmfQm zNYQxd@mBxVYMGr2KJ2~J%d}s^@0U!-Oht7mNkKl&?2|%fUN?L!r+sKBNWZg5)m}oo zAm-z&B<;;f|Lz3u-H>>5-rT@lXZViIOz6rq;R*AYtmwaf%{C1^!JGWkKW_j1FSAhc zkymn8@)RAhUGLrh9(EwIuPA-zeA#MFte9!C^f~hdUlo^I@6r!F!J{Vhp-Sn#3A^s~fb9V<-lorgY~A4% zJ~@2DZuYyLC*yQJzq@tm-anhi-`#&mPYN#D-1#He4j3t%1s;*b3=G`DAk4@xYmNj^ zP@=>&q9iy!t)x7$D3u`~F*C13&(AeP!Bo#s&%FEEcT1p}p414>G*3@01`Z&Hl|hP; zm4Ok+@&aOMC>s?08jQ?faV8+!kdcW&07ypxab`OUSUd~J1_4h=Mur#62pY{&2B7{4 z>Cbt)o~$voI?=w9d;ZDQBJZ3&uV>k5&AyrC zc!Sg$iv@mjO)HAO&SCmj!LVxH$I7Sk4n6mpc(;7!52nq>?U?VS7u4R~ZC%;Vx8mTX f{TpunS-6#3<)5&juMN{vkh?rx{an^LB{Ts5#J(&- literal 0 HcmV?d00001 From 68991d2928fdacb400045f6920f5bec45c7d0202 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 19:04:02 +0100 Subject: [PATCH 34/56] =?UTF-8?q?=F0=9F=9A=82=20Chemical=20transportation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mixtures can now be inserted into contraptions even if the contents aren't identical --- .../mixin/CombinedTankWrapperMixin.java | 25 +++++++++++++ .../mixin/MountedFluidStorageMixin.java | 36 +++++++++++++++++++ src/main/resources/destroy.mixins.json | 2 ++ 3 files changed, 63 insertions(+) create mode 100644 src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java create mode 100644 src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java diff --git a/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java b/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java new file mode 100644 index 000000000..06428c588 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java @@ -0,0 +1,25 @@ +package com.petrolpark.destroy.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.petrolpark.destroy.DestroyFluids; +import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import net.minecraftforge.fluids.FluidStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(CombinedTankWrapper.class) +public class CombinedTankWrapperMixin { + // Make fluid insertion into contraptions prioritize tanks that already contain mixtures + @WrapOperation( + method = "Lcom/simibubi/create/foundation/fluid/CombinedTankWrapper;fill(Lnet/minecraftforge/fluids/FluidStack;Lnet/minecraftforge/fluids/capability/IFluidHandler$FluidAction;)I", + at = @At( + value = "INVOKE", + target = "Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z" + ), + remap = false + ) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operation original) { + return original.call(fluid, other) || (DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)); + } +} diff --git a/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java new file mode 100644 index 000000000..1799b524f --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java @@ -0,0 +1,36 @@ +package com.petrolpark.destroy.mixin; + +import com.simibubi.create.content.contraptions.MountedFluidStorage; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.foundation.fluid.SmartFluidTank; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.fluids.FluidStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import com.petrolpark.destroy.core.fluid.GeniusFluidTankBehaviour.GeniusFluidTank; + +@Mixin(MountedFluidStorage.class) +public abstract class MountedFluidStorageMixin { + @Inject( + method = "Lcom/simibubi/create/content/contraptions/MountedFluidStorage;createMountedTank(Lnet/minecraft/world/level/block/entity/BlockEntity;)Lcom/simibubi/create/foundation/fluid/SmartFluidTank;", + at = @At("HEAD"), + cancellable = true, + remap = false + ) + private void createGeniusMountedTank(BlockEntity be, CallbackInfoReturnable cir) { + if(be instanceof FluidTankBlockEntity tank) { + cir.setReturnValue(new GeniusFluidTank( + tank.getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), + this::invokeOnFluidStackChanged)); + } + } + + @Invoker( + value = "onFluidStackChanged", + remap = false + ) + public abstract void invokeOnFluidStackChanged(FluidStack stack); +} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index e04e0913f..8aca1e26a 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -33,6 +33,7 @@ "BlazeBurnerBlockEntityMixin", "BlockMixin", "CartographyTableMenuMixin", + "CombinedTankWrapperMixin", "ConnectivityHandlerMixin", "DestroyFrictionModifier", "FilterItemStackMixin", @@ -48,6 +49,7 @@ "ItemEntityMixin", "LevelSettingsMixin", "MechanicalMixerBlockEntityMixin", + "MountedFluidStorageMixin", "MultiPlayerGameModeMixin", "PipeConnectionMixin", "PlayerMixin", From c2f5677db067565757b71c39e8a1cc269c288aec Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 21:41:01 +0100 Subject: [PATCH 35/56] =?UTF-8?q?=F0=9F=94=A8=20Fix=20hard=20dependency=20?= =?UTF-8?q?on=20JEI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/compat/jei/DestroyJEI.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/DestroyJEI.java b/src/main/java/com/petrolpark/destroy/compat/jei/DestroyJEI.java index 54a8e839b..18fd8f790 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/DestroyJEI.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/DestroyJEI.java @@ -76,6 +76,7 @@ import mezz.jei.api.JeiPlugin; import mezz.jei.api.constants.RecipeTypes; import mezz.jei.api.forge.ForgeTypes; +import mezz.jei.api.helpers.IJeiHelpers; import mezz.jei.api.helpers.IPlatformFluidHelper; import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.recipe.vanilla.IJeiAnvilRecipe; @@ -87,7 +88,6 @@ import mezz.jei.api.registration.IRecipeRegistration; import mezz.jei.api.registration.ISubtypeRegistration; import mezz.jei.api.runtime.IJeiRuntime; -import mezz.jei.library.plugins.vanilla.anvil.AnvilRecipe; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; @@ -330,7 +330,7 @@ public void registerRecipes(IRecipeRegistration registration) { registration.addRecipes(RecipeTypes.CRAFTING, ExtendedDurationFireworkRocketRecipe.exampleRecipes()); // Anvil repairs - registration.addRecipes(RecipeTypes.ANVIL, getAnvilRepairs()); + registration.addRecipes(RecipeTypes.ANVIL, getAnvilRepairs(registration)); }; @Override @@ -437,7 +437,7 @@ protected void finalizeBuilding(mezz.jei.api.recipe.RecipeType type, CreateRe }; - private static List getAnvilRepairs() { + private static List getAnvilRepairs(IRecipeRegistration registration) { List> repairables = List.of( Pair.of(DestroyItems.HAZMAT_SUIT.get(), DestroyArmorMaterials.HAZMAT.getRepairIngredient()), Pair.of(DestroyItems.HAZMAT_LEGGINGS.get(), DestroyArmorMaterials.HAZMAT.getRepairIngredient()), @@ -449,14 +449,19 @@ private static List getAnvilRepairs() { Pair.of(DestroyItems.GOLD_LABORATORY_GOGGLES.get(), DestroyItems.GOLD_LABORATORY_GOGGLES.get().getRepairIngredient()) ); - return repairables.stream().map(pair -> makeRepairRecipe(new ItemStack(pair.getFirst()), pair.getSecond())).toList(); + return repairables.stream().map(pair -> makeRepairRecipe(registration, new ItemStack(pair.getFirst()), pair.getSecond())).toList(); }; - public static IJeiAnvilRecipe makeRepairRecipe(ItemStack input, Ingredient repairItem) { + public static IJeiAnvilRecipe makeRepairRecipe(IRecipeRegistration registration, ItemStack input, Ingredient repairItem) { ItemStack halfDurability = input.copy(); halfDurability.setDamageValue(halfDurability.getMaxDamage() / 2); ItemStack threeQuarterDurability = input.copy(); threeQuarterDurability.setDamageValue(threeQuarterDurability.getMaxDamage() * 3 / 4); - return new AnvilRecipe(Collections.singletonList(halfDurability), Arrays.asList(repairItem.getItems()), Collections.singletonList(threeQuarterDurability), null); + + return registration.getVanillaRecipeFactory().createAnvilRecipe( + Collections.singletonList(halfDurability), + Arrays.asList(repairItem.getItems()), + Collections.singletonList(threeQuarterDurability) + ); }; }; From 2faac4bb5a8761fb9f9917cbc3065f720c2b6a61 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 27 Mar 2025 23:34:04 +0100 Subject: [PATCH 36/56] =?UTF-8?q?=E2=9D=8C=20Whoops,=20broke=20basins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mixin/CombinedTankWrapperMixin.java | 25 ------------------- src/main/resources/destroy.mixins.json | 1 - 2 files changed, 26 deletions(-) delete mode 100644 src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java diff --git a/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java b/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java deleted file mode 100644 index 06428c588..000000000 --- a/src/main/java/com/petrolpark/destroy/mixin/CombinedTankWrapperMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.petrolpark.destroy.mixin; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.petrolpark.destroy.DestroyFluids; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; -import net.minecraftforge.fluids.FluidStack; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(CombinedTankWrapper.class) -public class CombinedTankWrapperMixin { - // Make fluid insertion into contraptions prioritize tanks that already contain mixtures - @WrapOperation( - method = "Lcom/simibubi/create/foundation/fluid/CombinedTankWrapper;fill(Lnet/minecraftforge/fluids/FluidStack;Lnet/minecraftforge/fluids/capability/IFluidHandler$FluidAction;)I", - at = @At( - value = "INVOKE", - target = "Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z" - ), - remap = false - ) - private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operation original) { - return original.call(fluid, other) || (DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)); - } -} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 8aca1e26a..0b8b7af49 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -33,7 +33,6 @@ "BlazeBurnerBlockEntityMixin", "BlockMixin", "CartographyTableMenuMixin", - "CombinedTankWrapperMixin", "ConnectivityHandlerMixin", "DestroyFrictionModifier", "FilterItemStackMixin", From edfc0afb85e28ae18fc35e706fbb97d3a5174d6c Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Mar 2025 02:35:26 +0100 Subject: [PATCH 37/56] =?UTF-8?q?=F0=9F=94=A7=20More=20molecule=20renderin?= =?UTF-8?q?g=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed molecules not being rendered in the Vat and Colorimeter GUI --- .../com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java | 2 ++ .../vat/observation/colorimeter/ColorimeterScreen.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index b488d5f02..2abfb1023 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -166,6 +166,7 @@ public void render(int xPosition, int yPosition, GuiGraphics graphics) { RenderType renderType = RenderType.translucent(); UIRenderHelper.flipForGuiRender(poseStack); model.renderInto(poseStack, buffer.getBuffer(renderType)); + buffer.endBatch(); poseStack.popPose(); }; @@ -192,6 +193,7 @@ public void renderItem(int xPosition, int yPosition, int width, int height, GuiG RenderType renderType = RenderType.solid(); UIRenderHelper.flipForGuiRender(poseStack); model.renderInto(poseStack, buffer.getBuffer(renderType)); + buffer.endBatch(); poseStack.popPose(); }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java index a9a7a005b..25421ca92 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/observation/colorimeter/ColorimeterScreen.java @@ -121,7 +121,7 @@ protected void renderWindow(GuiGraphics graphics, int mX, int mY, float partialT ms.translate(guiLeft + 3, guiTop + 16, 100); GuiHelper.startStencil(graphics, 0, 0, 250, 85); MoleculeRenderer renderer = species.getRenderer(); - ms.translate(0d, (double)-renderer.getHeight() / 2d, 0); + ms.translate((double)-renderer.getWidth() / 2d, (double)-renderer.getHeight() / 2d, 0); renderer.render(125, 42, graphics); GuiHelper.endStencil(); ms.popPose(); From d4bfe445ddaeee17d6edc1478f39546636a65626 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 28 Mar 2025 03:00:49 +0100 Subject: [PATCH 38/56] =?UTF-8?q?=F0=9F=92=A8=20No=20pressure=20m8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed Vats having an incorrect pressure when under a perfect vacuum - Fixed Vats displaying the wrong amount of moles when under a perfect vacuum --- .../destroy/core/chemistry/vat/VatControllerBlockEntity.java | 2 +- .../destroy/core/chemistry/vat/VatFluidTankBehaviour.java | 2 +- .../com/petrolpark/destroy/core/chemistry/vat/VatScreen.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 6eff18141..681a6aebd 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -635,7 +635,7 @@ public float getPressure() { if (getLevel().isClientSide()) return pressure.getChaseTarget(); // It thinks getLevel() might be null (it's not) if (!getVatOptional().isPresent()) return 0f; if (getGasTank().isEmpty()) { - return getLiquidTank().getFluidAmount() == getLiquidTank().getCapacity() ? 0f : AIR_PRESSURE; // Return 0 for a vacuum, and normal air pressure for a full Vat + return getLiquidTank().getFluidAmount() == getLiquidTank().getCapacity() ? 0f : -AIR_PRESSURE; // Return 0 for a vacuum, and normal air pressure for a full Vat }; return LegacyReaction.GAS_CONSTANT * 1000f * getTemperature() * ReadOnlyMixture.readNBT(ReadOnlyMixture::new, getGasTank().getFluid().getOrCreateChildTag("Mixture")).getTotalConcentration() - AIR_PRESSURE; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java index 984485eb3..2a9f453fe 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java @@ -117,7 +117,7 @@ public ReadOnlyMixture getCombinedReadOnlyMixture() { }; for (Entry entry : moleculesAndMoles.entrySet()) { - mixture.addMolecule(entry.getKey(), entry.getValue() / totalVolume); //TODO use different volume as this makes things slow + mixture.addMolecule(entry.getKey(), entry.getValue()); }; return mixture; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatScreen.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatScreen.java index 79504ed8d..857dd3ed5 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatScreen.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatScreen.java @@ -172,7 +172,7 @@ protected void updateMoleculeList() { switch (selectedView) { case BOTH: { mixture = blockEntity.getCombinedReadOnlyMixture(); - amount = blockEntity.getVatOptional().map(Vat::getCapacity).orElse(0); + amount = (int)Constants.MILLIBUCKETS_PER_LITER; break; } case GAS: { fluid = blockEntity.getGasTankContents(); From 3b3f80306957990eb8267f6d40d65ed4d35b5ca4 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 29 Mar 2025 02:12:07 +0100 Subject: [PATCH 39/56] =?UTF-8?q?=F0=9F=A7=B9=20All=20about=20the=20little?= =?UTF-8?q?=20things?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed several advancements not being awarded - Fixed bonds not rendering when at a very specific angle (this mainly affected Cubane) - Fixed contraption fluid storage no longer accepting Mixtures after a world reload - Block of Plywood is no more - Added a quick fix for decaying items not displaying their timer properly (this should be done in Petrolpark's library but I don't want to maintain a second forked repo) - Fixed some recipes requiring salts not accepting the correct concentration (e.g. Calcium Cyanamide) --- .../destroy/DestroyAdvancementTrigger.java | 4 ++-- .../com/petrolpark/destroy/DestroyClient.java | 5 ++++ .../logistics/siphon/SiphonBlockEntity.java | 17 +++++++------- .../processing/glassblowing/BlowpipeItem.java | 10 ++++---- .../core/chemistry/MoleculeRenderer.java | 6 ++++- .../ingredient/fluid/SaltFluidIngredient.java | 7 +++++- .../mixin/MountedFluidStorageMixin.java | 19 +++++++++++++++ .../resources/assets/destroy/lang/en_us.json | 2 +- .../data/destroy/advancements/chrome.json | 23 ++++++++++--------- .../data/destroy/advancements/plastic.json | 2 +- 10 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/DestroyAdvancementTrigger.java b/src/main/java/com/petrolpark/destroy/DestroyAdvancementTrigger.java index 0c91f121f..91322b9d5 100644 --- a/src/main/java/com/petrolpark/destroy/DestroyAdvancementTrigger.java +++ b/src/main/java/com/petrolpark/destroy/DestroyAdvancementTrigger.java @@ -34,9 +34,9 @@ public enum DestroyAdvancementTrigger { COLORIMETER, COMPLETE_SEISMOGRAPH, CUT_ONIONS, - DISTILL("distill", "distillations"), + DISTILL("distill", "distillation"), CHARGE_WITH_DYNAMO("charge_with_dynamo", "dynamo_charging"), - ELECTROLYZE_WITH_DYNAMO("electrolyze_with_dynamo", "electrolyze_with_dynamo"), + ELECTROLYZE_WITH_DYNAMO("electrolyze_with_dynamo", "dynamo_electrolysis"), ETHYLANTHRAQUINONE, EXTRUDE, FILL_SEISMOGRAPH, diff --git a/src/main/java/com/petrolpark/destroy/DestroyClient.java b/src/main/java/com/petrolpark/destroy/DestroyClient.java index a02a5cc16..c9ecfcf58 100644 --- a/src/main/java/com/petrolpark/destroy/DestroyClient.java +++ b/src/main/java/com/petrolpark/destroy/DestroyClient.java @@ -1,5 +1,6 @@ package com.petrolpark.destroy; +import com.petrolpark.Petrolpark; import com.petrolpark.destroy.client.DestroyItemDisplayContexts; import com.petrolpark.destroy.client.DestroyPartials; import com.petrolpark.destroy.client.DestroyParticleTypes; @@ -9,6 +10,7 @@ import com.petrolpark.destroy.client.FogHandler; import com.petrolpark.destroy.core.extendedinventory.ExtendedInventoryClientHandler; +import com.petrolpark.item.decay.DecayingItemHandler; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @@ -24,6 +26,9 @@ public class DestroyClient { public static void clientInit(final FMLClientSetupEvent event) { event.enqueueWork(() -> { // Work which must be done on main thread DestroyItemProperties.register(); + + // TODO: This is supposed to be done by the Petrolpark library, remove this once this is properly fixed + Petrolpark.DECAYING_ITEM_HANDLER.set(new DecayingItemHandler.ClientDecayingItemHandler()); }); DestroyPonderTags.register(); DestroyPonderIndex.register(); diff --git a/src/main/java/com/petrolpark/destroy/content/logistics/siphon/SiphonBlockEntity.java b/src/main/java/com/petrolpark/destroy/content/logistics/siphon/SiphonBlockEntity.java index 2df80a9fb..204ea83a0 100644 --- a/src/main/java/com/petrolpark/destroy/content/logistics/siphon/SiphonBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/content/logistics/siphon/SiphonBlockEntity.java @@ -46,7 +46,6 @@ public class SiphonBlockEntity extends SmartBlockEntity implements IHaveLabGoggl public ScrollValueBehaviour settings; public DestroyAdvancementBehaviour advancementBehaviour; - private boolean giveAdvancementWhenEmptied = false; public SiphonBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -71,14 +70,12 @@ public void addBehaviours(List behaviours) { protected void read(CompoundTag tag, boolean clientPacket) { super.read(tag, clientPacket); leftToDrain = tag.getInt("LeftToDrain"); - if (tag.contains("GiveAdvancementWhenEmptied", Tag.TAG_BYTE)) giveAdvancementWhenEmptied = tag.getBoolean("GiveAdvancementWhenEmptied"); }; @Override protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); tag.putInt("LeftToDrain", leftToDrain); - if (advancementBehaviour.getPlayer() != null) tag.putBoolean("GiveAdvanementWhenEmptied", giveAdvancementWhenEmptied); }; @Override @@ -111,8 +108,10 @@ public SiphonFluidHandler(IFluidHandler... handlers) { public FluidStack drain(int maxDrain, FluidAction action) { maxDrain = Math.min(maxDrain, leftToDrain); FluidStack drained = super.drain(maxDrain, action); - if (action.execute()) leftToDrain -= drained.getAmount(); - checkAdvancement(); + if (action.execute()) { + leftToDrain -= drained.getAmount(); + if(!drained.isEmpty()) checkAdvancement(); + } return drained; }; @@ -122,13 +121,15 @@ public FluidStack drain(FluidStack resource, FluidAction action) { if (toDrain.isEmpty()) return FluidStack.EMPTY; toDrain.setAmount(Math.min(resource.getAmount(), leftToDrain)); FluidStack drained = super.drain(toDrain, action); - if (action.execute()) leftToDrain -= drained.getAmount(); - checkAdvancement(); + if (action.execute()) { + leftToDrain -= drained.getAmount(); + if(!drained.isEmpty()) checkAdvancement(); + } return drained; }; private void checkAdvancement() { - if (giveAdvancementWhenEmptied && leftToDrain == 0) { + if (leftToDrain == 0) { advancementBehaviour.awardDestroyAdvancement(DestroyAdvancementTrigger.SIPHON); }; }; diff --git a/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeItem.java b/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeItem.java index 2cf95234f..ecae331a2 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeItem.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeItem.java @@ -205,7 +205,12 @@ public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotI tag.putBoolean("Blowing", false); }; - if (increaseProgress && progress < BlowpipeBlockEntity.BLOWING_DURATION) tag.putInt("Progress", progress + 1); + if (increaseProgress && progress < BlowpipeBlockEntity.BLOWING_DURATION) { + tag.putInt("Progress", progress + 1); + if(progress < BlowpipeBlockEntity.BLOWING_DURATION && progress + 1 >= BlowpipeBlockEntity.BLOWING_DURATION && entity instanceof Player player) { + DestroyAdvancementTrigger.BLOWPIPE.award(level, player); + } + } }; @Override @@ -227,9 +232,6 @@ public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livi tag.putInt("Progress", 0); tag.putInt("LastProgress", 0); tag.put("Tank", new FluidTank(BlowpipeBlockEntity.TANK_CAPACITY).writeToNBT(new CompoundTag())); // Empty the Tank - if (livingEntity instanceof Player player) { - DestroyAdvancementTrigger.BLOWPIPE.award(level, player); - }; }; return stack; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index 2abfb1023..50c8a2411 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -10,6 +10,7 @@ import com.jozufozu.flywheel.core.model.ModelUtil; import com.mojang.blaze3d.vertex.*; import com.mojang.math.Axis; +import com.petrolpark.destroy.Destroy; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.Minecraft; @@ -404,7 +405,10 @@ public static BondRenderInstance fromZig(BondType type, Vec3 zig) { Vec3 z = zig.normalize(); Vec3 axis = bond.cross(z); Quaternionf q = new Quaternionf(axis.x(), axis.y(), axis.z(), (float)bond.dot(z) + (float)Math.sqrt(bond.lengthSqr() * z.lengthSqr())); - return new BondRenderInstance(type, new Quaternionf(q.normalize())); + if(!q.normalize().isFinite()) + q = new Quaternionf(0f, 0f, 0f, 1f); // identity + + return new BondRenderInstance(type, q); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/core/recipe/ingredient/fluid/SaltFluidIngredient.java b/src/main/java/com/petrolpark/destroy/core/recipe/ingredient/fluid/SaltFluidIngredient.java index 70834c20c..48dde9cf1 100644 --- a/src/main/java/com/petrolpark/destroy/core/recipe/ingredient/fluid/SaltFluidIngredient.java +++ b/src/main/java/com/petrolpark/destroy/core/recipe/ingredient/fluid/SaltFluidIngredient.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.List; +import com.google.common.math.IntMath; import com.google.gson.JsonObject; import com.petrolpark.destroy.chemistry.legacy.LegacyMixture; import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; @@ -41,7 +42,11 @@ public void addNBT(CompoundTag fluidTag) { @Override protected boolean testMixture(LegacyMixture mixture) { - return mixture.hasUsableMolecule(cation, minConcentration * cation.getCharge(), maxConcentration * cation.getCharge(), (molecule) -> molecule == anion) && mixture.hasUsableMolecule(anion, minConcentration * -anion.getCharge(), maxConcentration * -anion.getCharge(), (molecule) -> molecule == cation); + int gcd = IntMath.gcd(cation.getCharge(), -anion.getCharge()); + float cationMultiplier = (float)-anion.getCharge() / gcd; + float anionMultiplier = (float)cation.getCharge() / gcd; + return mixture.hasUsableMolecule(cation, minConcentration * cationMultiplier, maxConcentration * cationMultiplier, (molecule) -> molecule == anion) + && mixture.hasUsableMolecule(anion, minConcentration * anionMultiplier, maxConcentration * anionMultiplier, (molecule) -> molecule == cation); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java index 1799b524f..17e50790b 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java @@ -1,17 +1,24 @@ package com.petrolpark.destroy.mixin; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.simibubi.create.content.contraptions.MountedFluidStorage; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.foundation.fluid.SmartFluidTank; +import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.fluids.FluidStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.petrolpark.destroy.core.fluid.GeniusFluidTankBehaviour.GeniusFluidTank; +import java.util.function.Consumer; + @Mixin(MountedFluidStorage.class) public abstract class MountedFluidStorageMixin { @Inject( @@ -28,6 +35,18 @@ private void createGeniusMountedTank(BlockEntity be, CallbackInfoReturnable original) { + return new GeniusFluidTank(capacity, updateCallback); + } + @Invoker( value = "onFluidStackChanged", remap = false diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index bf10ad918..b11439730 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -229,7 +229,7 @@ "block.destroy.picric_acid_block": "Picric Acid Block", "block.destroy.picric_acid_block.tooltip": "PICRIC_ACID_BLOCK", "block.destroy.picric_acid_block.tooltip.summary": "This _powerful explosive_ can even detonate _underwater_.", - "block.destroy.platinum_block": "Block of Plywood", + "block.destroy.platinum_block": "Block of Platinum", "block.destroy.platinum_periodic_table_block": "Platinum Element Block", "block.destroy.plywood": "Plywood", "block.destroy.pollutometer": "Pollutometer", diff --git a/src/main/resources/data/destroy/advancements/chrome.json b/src/main/resources/data/destroy/advancements/chrome.json index ba71aa746..abf597af4 100644 --- a/src/main/resources/data/destroy/advancements/chrome.json +++ b/src/main/resources/data/destroy/advancements/chrome.json @@ -1,24 +1,25 @@ { "parent": "destroy:urinate", "criteria": { - "hold": { + "hold_ingot": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ - { - "item": "destroy:nether_crocoite" - }, - { - "tag": "forge:raw_materials/chromium" - }, { "tag": "forge:ingots/chromium" - }, - { - "item": "destroy:crushed_raw_chromium" } ] } + }, + "hold_nugget": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "forge:nuggets/chromium" + } + ] + } } }, "display": { @@ -35,7 +36,7 @@ }, "requirements": [ [ - "hold" + "hold_ingot", "hold_nugget" ] ] } \ No newline at end of file diff --git a/src/main/resources/data/destroy/advancements/plastic.json b/src/main/resources/data/destroy/advancements/plastic.json index 70a1768d1..e9ee1b479 100644 --- a/src/main/resources/data/destroy/advancements/plastic.json +++ b/src/main/resources/data/destroy/advancements/plastic.json @@ -6,7 +6,7 @@ "conditions": { "items": [ { - "tag": "destroy:plastic" + "tag": "destroy:plastics" } ] } From d13545adde1e2aee6f2aea82626b904c2e7baeb0 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 30 Mar 2025 03:01:32 +0200 Subject: [PATCH 40/56] =?UTF-8?q?=F0=9F=9B=9E=20Flywheel=20real?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added instanced rendering to the Pumpjack, Tapper, Mechanical Sieve and Keypunch - Fixed Pumpjack shaft briefly rendering at the wrong angle when placed in certain locations - Fixed crash caused by looking at a circuit mask on the ground with Jade --- .../destroy/DestroyBlockEntityTypes.java | 11 ++- .../oil/pumpjack/PumpjackBlockEntity.java | 26 +++++- .../oil/pumpjack/PumpjackInstance.java | 20 ++--- .../oil/pumpjack/PumpjackRenderer.java | 8 +- .../processing/dynamo/DynamoCogInstance.java | 6 -- .../sieve/MechanicalSieveInstance.java | 83 +++++++++++++++++++ .../sieve/MechanicalSieveRenderer.java | 3 + .../processing/treetap/TreeTapInstance.java | 56 +++++++++++++ .../processing/treetap/TreeTapRenderer.java | 4 +- .../trypolithography/CircuitMaskItem.java | 5 ++ .../keypunch/KeypunchInstance.java | 65 +++++++++++++++ .../keypunch/KeypunchRenderer.java | 6 +- .../models/block/mechanical_sieve/shaft.json | 35 ++++---- .../destroy/models/block/tree_tap/arm.json | 50 +++++------ 14 files changed, 305 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveInstance.java create mode 100644 src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java create mode 100644 src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchInstance.java diff --git a/src/main/java/com/petrolpark/destroy/DestroyBlockEntityTypes.java b/src/main/java/com/petrolpark/destroy/DestroyBlockEntityTypes.java index 95e0c5647..c5fb81901 100644 --- a/src/main/java/com/petrolpark/destroy/DestroyBlockEntityTypes.java +++ b/src/main/java/com/petrolpark/destroy/DestroyBlockEntityTypes.java @@ -7,6 +7,7 @@ import com.petrolpark.destroy.content.logistics.siphon.SiphonRenderer; import com.petrolpark.destroy.content.oil.pumpjack.PumpjackBlockEntity; import com.petrolpark.destroy.content.oil.pumpjack.PumpjackCamBlockEntity; +import com.petrolpark.destroy.content.oil.pumpjack.PumpjackInstance; import com.petrolpark.destroy.content.oil.pumpjack.PumpjackRenderer; import com.petrolpark.destroy.content.processing.ageing.AgeingBarrelBlockEntity; import com.petrolpark.destroy.content.processing.ageing.AgeingBarrelRenderer; @@ -24,15 +25,17 @@ import com.petrolpark.destroy.content.processing.glassblowing.BlowpipeBlockEntity; import com.petrolpark.destroy.content.processing.glassblowing.BlowpipeBlockEntityRenderer; import com.petrolpark.destroy.content.processing.sieve.MechanicalSieveBlockEntity; +import com.petrolpark.destroy.content.processing.sieve.MechanicalSieveInstance; import com.petrolpark.destroy.content.processing.sieve.MechanicalSieveRenderer; import com.petrolpark.destroy.content.processing.treetap.TreeTapBlockEntity; +import com.petrolpark.destroy.content.processing.treetap.TreeTapInstance; import com.petrolpark.destroy.content.processing.treetap.TreeTapRenderer; import com.petrolpark.destroy.content.processing.trypolithography.keypunch.KeypunchBlockEntity; +import com.petrolpark.destroy.content.processing.trypolithography.keypunch.KeypunchInstance; import com.petrolpark.destroy.content.processing.trypolithography.keypunch.KeypunchRenderer; import com.petrolpark.destroy.content.redstone.programmer.RedstoneProgrammerBlockEntity; import com.petrolpark.destroy.content.redstone.programmer.RedstoneProgrammerBlockEntityRenderer; import com.petrolpark.destroy.content.sandcastle.SandCastleBlockEntity; -import com.petrolpark.destroy.core.block.entity.instance.HorizontalShaftlessCogwheelInstance; import com.petrolpark.destroy.core.chemistry.storage.ElementTankBlockEntity; import com.petrolpark.destroy.core.chemistry.storage.ElementTankRenderer; import com.petrolpark.destroy.core.chemistry.storage.SimpleMixtureTankBlockEntity.SimplePlaceableMixtureTankBlockEntity; @@ -138,7 +141,7 @@ public class DestroyBlockEntityTypes { public static final BlockEntityEntry KEYPUNCH = REGISTRATE .blockEntity("keypunch", KeypunchBlockEntity::new) - .instance(() -> HorizontalShaftlessCogwheelInstance::new) + .instance(() -> KeypunchInstance::new) .validBlocks(DestroyBlocks.KEYPUNCH) .renderer(() -> KeypunchRenderer::new) .register(); @@ -151,6 +154,7 @@ public class DestroyBlockEntityTypes { public static final BlockEntityEntry MECHANICAL_SIEVE = REGISTRATE .blockEntity("mechanical_sieve", MechanicalSieveBlockEntity::new) + .instance(() -> MechanicalSieveInstance::new) .validBlock(DestroyBlocks.MECHANICAL_SIEVE) .renderer(() -> MechanicalSieveRenderer::new) .register(); @@ -163,7 +167,7 @@ public class DestroyBlockEntityTypes { public static final BlockEntityEntry PUMPJACK = REGISTRATE .blockEntity("pumpjack", PumpjackBlockEntity::new) - //.instance(() -> PumpjackInstance::new, false) Can't use instancing because that can't render cutout for some reason + .instance(() -> PumpjackInstance::new) .validBlocks(DestroyBlocks.PUMPJACK) .renderer(() -> PumpjackRenderer::new) .register(); @@ -198,6 +202,7 @@ public class DestroyBlockEntityTypes { public static final BlockEntityEntry TREE_TAP = REGISTRATE .blockEntity("tree_tap", TreeTapBlockEntity::new) + .instance(() -> TreeTapInstance::new) .validBlock(DestroyBlocks.TREE_TAP) .renderer(() -> TreeTapRenderer::new) .register(); diff --git a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackBlockEntity.java b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackBlockEntity.java index a014467b9..e6a51df1e 100644 --- a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackBlockEntity.java @@ -149,6 +149,24 @@ public Float getTargetAngle() { return angle; }; + public float getRenderAngle() { + Float angle = getTargetAngle(); + if(angle == null) + { + BlockState blockState = getBlockState(); + Direction facing = PumpjackBlock.getFacing(blockState); + Direction.Axis axis = facing.getCounterClockWise().getAxis(); + BlockPos pos = getCamPos(); + double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) + + ((axis == Direction.Axis.Z) ? 0 : pos.getZ())) % 2; + angle = d == 0 ? 22.5f * Mth.PI / 180.f : 0f; + + if (axis.isHorizontal() && (facing.getAxis() == Axis.X ^ facing.getAxisDirection() == AxisDirection.NEGATIVE)) + angle *= -1; + } + return angle; + }; + @OnlyIn(Dist.CLIENT) public void playClientSound() { if (getTargetAngle() == null) return; @@ -164,14 +182,18 @@ public void playClientSound() { }; }; + public BlockPos getCamPos() { + Direction facing = PumpjackBlock.getFacing(getBlockState()); + return getBlockPos().relative(facing, 1); + } + @Nullable @SuppressWarnings("null") public PumpjackCamBlockEntity getCam() { PumpjackCamBlockEntity cam = source.get(); if (cam == null || cam.isRemoved() || !cam.canPower(getBlockPos())) { if (cam != null) source = new WeakReference<>(null); - Direction facing = PumpjackBlock.getFacing(getBlockState()); - BlockEntity anyCamAt = getLevel().getBlockEntity(getBlockPos().relative(facing, 1)); // It thinks getLevel() might be null + BlockEntity anyCamAt = getLevel().getBlockEntity(getCamPos()); // It thinks getLevel() might be null if (anyCamAt instanceof PumpjackCamBlockEntity newCam && newCam.canPower(getBlockPos())) { cam = newCam; source = new WeakReference<>(cam); diff --git a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackInstance.java b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackInstance.java index 7cf5fc22e..07d5d8fb1 100644 --- a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackInstance.java +++ b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackInstance.java @@ -8,6 +8,7 @@ import com.petrolpark.destroy.client.DestroyPartials; import com.simibubi.create.foundation.utility.AngleHelper; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; @@ -18,6 +19,8 @@ public class PumpjackInstance extends BlockEntityInstance i protected final ModelData beam; protected final ModelData pump; + private static final double beamRotation = Math.asin(5 / 17d); + public PumpjackInstance(MaterialManager materialManager, PumpjackBlockEntity blockEntity) { super(materialManager, blockEntity); @@ -31,7 +34,7 @@ public PumpjackInstance(MaterialManager materialManager, PumpjackBlockEntity blo .getModel(DestroyPartials.PUMPJACK_LINKAGE, blockState) .createInstance(); - beam = materialManager.defaultSolid() + beam = materialManager.defaultCutout() .material(Materials.TRANSFORMED) .getModel(DestroyPartials.PUMPJACK_BEAM, blockState) .createInstance(); @@ -44,14 +47,7 @@ public PumpjackInstance(MaterialManager materialManager, PumpjackBlockEntity blo @Override public void beginFrame() { - Float angle = blockEntity.getTargetAngle(); - if (angle == null) { - cam.setEmptyTransform(); - linkage.setEmptyTransform(); - beam.setEmptyTransform(); - pump.setEmptyTransform(); - return; - }; + float angle = blockEntity.getRenderAngle(); Direction facing = PumpjackBlock.getFacing(blockState); @@ -65,10 +61,10 @@ public void beginFrame() { .unCentre(); transformed(linkage, facing) - .translate(0d, -5 / 16d, 1d) + .translate(0d, -4.5 / 16d, 1d) .translate(0d, Mth.sin(angle) * 5 / 16d, -Mth.cos(angle) * 5 / 16d) .centre() - .rotateX(Mth.cos(angle) * 10d) + .rotateXRadians((Mth.cos(angle)) * beamRotation * 0.73d) .centre() .translate(0d, 0d, -1d) .unCentre() @@ -77,7 +73,7 @@ public void beginFrame() { transformed(beam, facing) .translate(0d, 1d, 0d) .centre() - .rotateX((Mth.sin(angle) - 1) * -18d) + .rotateXRadians((Mth.sin(angle)) * -beamRotation) .centre() .translate(0d, -1d, 0d) .unCentre() diff --git a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackRenderer.java b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackRenderer.java index 67bef0f74..18a17a914 100644 --- a/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/oil/pumpjack/PumpjackRenderer.java @@ -1,9 +1,11 @@ package com.petrolpark.destroy.content.oil.pumpjack; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.petrolpark.destroy.client.DestroyPartials; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; @@ -12,6 +14,7 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.level.block.state.BlockState; @@ -24,10 +27,9 @@ public PumpjackRenderer(BlockEntityRendererProvider.Context context) {} @Override protected void renderSafe(PumpjackBlockEntity pumpjack, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light, int overlay) { - //if (Backend.canUseInstancing(pumpjack.getLevel())) return; Can't use instancing because it can't render cutout for some reason + if (Backend.canUseInstancing(pumpjack.getLevel())) return; - Float angle = pumpjack.getTargetAngle(); - if (angle == null) angle = 0f; + float angle = pumpjack.getRenderAngle(); BlockState blockState = pumpjack.getBlockState(); Direction facing = PumpjackBlock.getFacing(blockState); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/dynamo/DynamoCogInstance.java b/src/main/java/com/petrolpark/destroy/content/processing/dynamo/DynamoCogInstance.java index 75196fd0c..d671f3e58 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/dynamo/DynamoCogInstance.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/dynamo/DynamoCogInstance.java @@ -15,12 +15,6 @@ public DynamoCogInstance(MaterialManager modelManager, KineticBlockEntity blockE super(modelManager, blockEntity); }; - @Override - public void updateLight() { - super.updateLight(); - relight(pos); - }; - @Override protected Instancer getModel() { BlockState state = blockEntity.getBlockState(); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveInstance.java b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveInstance.java new file mode 100644 index 000000000..600151505 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveInstance.java @@ -0,0 +1,83 @@ +package com.petrolpark.destroy.content.processing.sieve; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.petrolpark.destroy.client.DestroyPartials; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.utility.AngleHelper; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +public class MechanicalSieveInstance extends SingleRotatingInstance implements DynamicInstance { + + protected final ModelData sieve; + protected final ModelData linkages; + + public MechanicalSieveInstance(MaterialManager materialManager, MechanicalSieveBlockEntity blockEntity) { + super(materialManager, blockEntity); + + sieve = materialManager.defaultCutout() + .material(Materials.TRANSFORMED) + .getModel(DestroyPartials.MECHANICAL_SIEVE, blockState) + .createInstance(); + + linkages = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(DestroyPartials.MECHANICAL_SIEVE_LINKAGES, blockState) + .createInstance(); + + updateAnimation(); + } + + @Override + public void beginFrame() { + updateAnimation(); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, sieve, linkages); + } + + @Override + public void remove() { + super.remove(); + sieve.delete(); + linkages.delete(); + } + + private void updateAnimation() { + Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); + float angle = KineticBlockEntityRenderer.getAngleForTe(blockEntity, blockEntity.getBlockPos(), axis); + Direction facing = blockState.getValue(MechanicalSieveBlock.X) ? Direction.EAST : Direction.SOUTH; + + float offset = (float)(Mth.sin(angle) * 2 / 16d); + + sieve.loadIdentity() + .translate(getInstancePosition()) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .unCentre() + .translate(offset, 0d , 0d); + + linkages.loadIdentity() + .translate(getInstancePosition()) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .translate(offset, 0d , 0d) + .rotateZRadians(-angle) + .unCentre(); + } + + @Override + protected Instancer getModel() { + Direction facing = blockState.getValue(MechanicalSieveBlock.X) ? Direction.EAST : Direction.SOUTH; + return getRotatingMaterial().getModel(DestroyPartials.MECHANICAL_SIEVE_SHAFT, blockState, facing); + } +} diff --git a/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java index 4084cf72f..954ac66af 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java @@ -1,5 +1,6 @@ package com.petrolpark.destroy.content.processing.sieve; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -25,6 +26,8 @@ public MechanicalSieveRenderer(Context context) { @Override protected void renderSafe(MechanicalSieveBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + if (Backend.canUseInstancing(be.getLevel())) return; + BlockState state = be.getBlockState(); boolean x = state.getValue(MechanicalSieveBlock.X); VertexConsumer vc = buffer.getBuffer(RenderType.cutoutMipped()); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java new file mode 100644 index 000000000..ea0f04f54 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java @@ -0,0 +1,56 @@ +package com.petrolpark.destroy.content.processing.treetap; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.petrolpark.destroy.client.DestroyPartials; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; + +public class TreeTapInstance extends ShaftInstance implements DynamicInstance { + + final Direction facing; + protected final OrientedData arm; + + public TreeTapInstance(MaterialManager materialManager, TreeTapBlockEntity blockEntity) { + super(materialManager, blockEntity); + + facing = blockState.getValue(HORIZONTAL_FACING); + arm = getOrientedMaterial().getModel(DestroyPartials.TREE_TAP_ARM, blockState, facing).createInstance() + .setPivot(0.5f, 0.5f, 0.5f); + + updateAnimation(); + } + + @Override + public void beginFrame() { + updateAnimation(); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, arm); + } + + @Override + public void remove() { + super.remove(); + arm.delete(); + } + + private void updateAnimation() { + float angle = 9f * Mth.sin((float)Math.toRadians((AnimationTickHolder.getRenderTime() * blockEntity.getSpeed() * 3f / 10) % 360)); + + Vector3f axis = facing.getCounterClockWise().step(); + + arm.setPosition(getInstancePosition()) + .setRotation(new Quaternionf().rotationAxis((float)Math.toRadians(angle), axis)); + } +} diff --git a/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapRenderer.java b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapRenderer.java index 09e7c6b92..98d25a0b6 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapRenderer.java @@ -1,5 +1,6 @@ package com.petrolpark.destroy.content.processing.treetap; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.vertex.PoseStack; import com.petrolpark.destroy.client.DestroyPartials; import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; @@ -21,7 +22,7 @@ public TreeTapRenderer(Context context) { @Override protected void renderSafe(TreeTapBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - //if (Backend.canUseInstancing(be.getLevel())) return; + if (Backend.canUseInstancing(be.getLevel())) return; BlockState state = be.getBlockState(); Direction facing = state.getValue(TreeTapBlock.HORIZONTAL_FACING); @@ -31,7 +32,6 @@ protected void renderSafe(TreeTapBlockEntity be, float partialTicks, PoseStack m .rotate(9f * Mth.sin(getAngleForTe(be, be.getBlockPos(), facing.getClockWise().getAxis())), facing.getClockWise().getAxis()) .rotateToFace(facing.getOpposite()) .unCentre() - .translate(0f, 12 / 16f, 7 / 16f) .light(light) .renderInto(ms, buffer.getBuffer(RenderType.solid())); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java index b1b144da5..7a3c5a159 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java @@ -14,6 +14,7 @@ import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; @@ -97,6 +98,10 @@ public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotI public void appendHoverText(ItemStack stack, Level level, List tooltipComponents, TooltipFlag isAdvanced) { super.appendHoverText(stack, level, tooltipComponents, isAdvanced); if (stack.getOrCreateTag().contains("HideContaminants")) return; + + if(level == null) // Fixes a crash caused by Jade + level = Minecraft.getInstance().level; + List previousPunchers = getContaminants(stack); tooltipComponents.add(Component.literal(" ")); tooltipComponents.add(DestroyLang.translate("tooltip.circuit_mask.punched_by", previousPunchers.size()).style(ChatFormatting.GRAY).component()); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchInstance.java b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchInstance.java new file mode 100644 index 000000000..a0bcafdb2 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchInstance.java @@ -0,0 +1,65 @@ +package com.petrolpark.destroy.content.processing.trypolithography.keypunch; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.petrolpark.destroy.client.DestroyPartials; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogInstance; +import com.simibubi.create.foundation.render.AllMaterialSpecs; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class KeypunchInstance extends EncasedCogInstance implements DynamicInstance { + + protected final ModelData piston; + + public KeypunchInstance(MaterialManager materialManager, KeypunchBlockEntity blockEntity) { + super(materialManager, blockEntity, false); + + piston = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(DestroyPartials.KEYPUNCH_PISTON, blockState) + .createInstance(); + + updateAnimation(); + } + + @Override + public void beginFrame() { + updateAnimation(); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, piston); + } + + @Override + public void remove() { + super.remove(); + piston.delete(); + } + + @Override + protected Instancer getCogModel() { + return materialManager.defaultSolid() + .material(AllMaterialSpecs.ROTATING) + .getModel(AllPartialModels.SHAFTLESS_COGWHEEL, blockEntity.getBlockState()); + } + + private void updateAnimation() { + KeypunchBlockEntity be = (KeypunchBlockEntity)blockEntity; + CircuitPunchingBehaviour behaviour = be.punchingBehaviour; + float renderedHeadOffset = behaviour.getRenderedPistonOffset(AnimationTickHolder.getPartialTicks()); + + int pistonPos = be.getActualPosition(); + + piston.loadIdentity() + .translate(getInstancePosition()) + .translate((4 + 2 * (pistonPos % 4)) / 16f, - (6.1f + (renderedHeadOffset * 12.5f)) / 16f, (4 + 2 * (pistonPos / 4)) / 16f); + } +} diff --git a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchRenderer.java b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchRenderer.java index 4b73a9f5d..5781ffe12 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/keypunch/KeypunchRenderer.java @@ -1,5 +1,6 @@ package com.petrolpark.destroy.content.processing.trypolithography.keypunch; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.vertex.PoseStack; import com.petrolpark.destroy.client.DestroyPartials; import com.simibubi.create.AllPartialModels; @@ -25,6 +26,9 @@ public boolean shouldRenderOffScreen(KeypunchBlockEntity be) { @Override protected void renderSafe(KeypunchBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + if (Backend.canUseInstancing(be.getLevel())) return; + BlockState blockState = be.getBlockState(); CircuitPunchingBehaviour behaviour = be.punchingBehaviour; float renderedHeadOffset = behaviour.getRenderedPistonOffset(partialTicks); @@ -34,8 +38,6 @@ protected void renderSafe(KeypunchBlockEntity be, float partialTicks, PoseStack headRender.translate((4 + 2 * (pistonPos % 4)) / 16f, - (6.1f + (renderedHeadOffset * 12.5f)) / 16f, (4 + 2 * (pistonPos / 4)) / 16f) .light(light) .renderInto(ms, buffer.getBuffer(RenderType.solid())); - - super.renderSafe(be, partialTicks, ms, buffer, light, overlay); }; @Override diff --git a/src/main/resources/assets/destroy/models/block/mechanical_sieve/shaft.json b/src/main/resources/assets/destroy/models/block/mechanical_sieve/shaft.json index ba6d4f821..2224684fb 100644 --- a/src/main/resources/assets/destroy/models/block/mechanical_sieve/shaft.json +++ b/src/main/resources/assets/destroy/models/block/mechanical_sieve/shaft.json @@ -8,31 +8,30 @@ }, "elements": [ { - "from": [6, 14, 6], - "to": [10, 16, 10], + "from": [6, 6, 14], + "to": [10, 10, 16], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": { - "north": {"uv": [6, 14, 10, 16], "rotation": 180, "texture": "#0"}, - "east": {"uv": [6, 0, 10, 2], "rotation": 180, "texture": "#0"}, - "south": {"uv": [6, 14, 10, 16], "texture": "#0"}, - "west": {"uv": [6, 0, 10, 2], "texture": "#0"}, - "up": {"uv": [8, 0, 6, 2], "texture": "#2"}, - "down": {"uv": [6, 0, 8, 2], "rotation": 180, "texture": "#2"} + "north": {"uv": [6, 0, 8, 2], "texture": "#2"}, + "east": {"uv": [6, 0, 10, 2], "rotation": 90, "texture": "#0"}, + "south": {"uv": [8, 0, 6, 2], "texture": "#2"}, + "west": {"uv": [6, 0, 10, 2], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 14, 10, 16], "texture": "#0"}, + "down": {"uv": [6, 14, 10, 16], "texture": "#0"} } }, { - "from": [6, 0, 6], - "to": [10, 2, 10], + "from": [6, 6, 0], + "to": [10, 10, 2], "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 8]}, "faces": { - "north": {"uv": [6, 0, 10, 2], "rotation": 180, "texture": "#0"}, - "east": {"uv": [6, 0, 10, 2], "rotation": 180, "texture": "#0"}, - "south": {"uv": [6, 0, 10, 2], "texture": "#0"}, - "west": {"uv": [6, 0, 10, 2], "texture": "#0"}, - "up": {"uv": [8, 0, 6, 2], "texture": "#2"}, - "down": {"uv": [6, 0, 8, 2], "rotation": 180, "texture": "#2"} + "north": {"uv": [6, 0, 8, 2], "texture": "#2"}, + "east": {"uv": [6, 0, 10, 2], "rotation": 90, "texture": "#0"}, + "south": {"uv": [8, 0, 6, 2], "texture": "#2"}, + "west": {"uv": [6, 0, 10, 2], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 0, 10, 2], "texture": "#0"}, + "down": {"uv": [6, 0, 10, 2], "texture": "#0"} } } - ], - "display": {} + ] } \ No newline at end of file diff --git a/src/main/resources/assets/destroy/models/block/tree_tap/arm.json b/src/main/resources/assets/destroy/models/block/tree_tap/arm.json index c9a955592..322355143 100644 --- a/src/main/resources/assets/destroy/models/block/tree_tap/arm.json +++ b/src/main/resources/assets/destroy/models/block/tree_tap/arm.json @@ -10,9 +10,9 @@ "elements": [ { "name": "Pinky", - "from": [4, 11, -1.95], - "to": [6, 15, 3.05], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [4, 23, 5.05], + "to": [6, 27, 10.05], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [0, 0, 2, 4], "rotation": 180, "texture": "#1"}, "east": {"uv": [0, 0, 4, 5], "rotation": 90, "texture": "#1"}, @@ -24,9 +24,9 @@ }, { "name": "Middle", - "from": [6, 12, -2], - "to": [8, 16, 3], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [6, 24, 5], + "to": [8, 28, 10], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [0, 0, 2, 4], "rotation": 180, "texture": "#1"}, "east": {"uv": [4, 8, 0, 13], "rotation": 90, "texture": "#1"}, @@ -38,9 +38,9 @@ }, { "name": "Index", - "from": [8, 14, -2], - "to": [10, 16, 6], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [8, 26, 5], + "to": [10, 28, 13], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [0, 0, 2, 2], "texture": "#1"}, "east": {"uv": [2, 1, 4, 9], "rotation": 270, "texture": "#1"}, @@ -52,9 +52,9 @@ }, { "name": "Thumb", - "from": [8, 12, -2], - "to": [12, 14, 1], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [8, 24, 5], + "to": [12, 26, 8], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [2, 0, 0, 4], "rotation": 90, "texture": "#1"}, "east": {"uv": [0, 1, 2, 4], "rotation": 270, "texture": "#1"}, @@ -66,9 +66,9 @@ }, { "name": "Palm", - "from": [5, 10, -2], - "to": [11, 12, 1], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [5, 22, 5], + "to": [11, 24, 8], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [1, 2, 3, 8], "rotation": 90, "texture": "#1"}, "east": {"uv": [1, 4, 3, 7], "rotation": 90, "texture": "#1"}, @@ -80,9 +80,9 @@ }, { "name": "Wrist", - "from": [6, 9, -1.95], - "to": [10.05, 12, 2], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [6, 21, 5.05], + "to": [10.05, 24, 9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [3, 0, 6, 4], "rotation": 90, "texture": "#0"}, "east": {"uv": [4, 0, 7, 4], "rotation": 90, "texture": "#0"}, @@ -94,9 +94,9 @@ }, { "name": "Cuff", - "from": [5, 7, -3], - "to": [11, 9, 3], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [5, 19, 4], + "to": [11, 21, 10], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [0, 14, 6, 16], "rotation": 180, "texture": "#2"}, "east": {"uv": [0, 14, 6, 16], "rotation": 180, "texture": "#2"}, @@ -108,9 +108,9 @@ }, { "name": "Arm", - "from": [6, -2, -2], - "to": [10, 7, 2], - "rotation": {"angle": 0, "axis": "x", "origin": [8, 0, 0]}, + "from": [6, 10, 5], + "to": [10, 19, 9], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 12, 7]}, "faces": { "north": {"uv": [0, 0, 4, 9], "texture": "#2"}, "east": {"uv": [0, 0, 4, 9], "texture": "#2"}, @@ -158,7 +158,7 @@ "groups": [ { "name": "Hand", - "origin": [8, 8, 8], + "origin": [8, 20, 15], "color": 0, "children": [0, 1, 2, 3, 4, 5, 6, 7] } From 9de49843d3f64c759956216be7e57398796d0fdc Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 30 Mar 2025 16:40:54 +0200 Subject: [PATCH 41/56] =?UTF-8?q?=F0=9F=8F=83=20Faster=20molecule=20render?= =?UTF-8?q?ing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implemented batched rendering for molecules in JEI (this should actually be usable now) --- .../compat/jei/MoleculeJEIIngredient.java | 13 ++- .../jei/render/MoleculeBatchRenderer.java | 94 +++++++++++++++++++ .../core/chemistry/MoleculeRenderer.java | 74 +++++++-------- 3 files changed, 138 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/petrolpark/destroy/compat/jei/render/MoleculeBatchRenderer.java diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java index f51e1325a..be737b2ad 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java @@ -13,6 +13,7 @@ import com.petrolpark.destroy.chemistry.legacy.ReadOnlyMixture; import com.petrolpark.destroy.chemistry.legacy.index.DestroyMolecules; import com.petrolpark.destroy.chemistry.minecraft.MixtureFluid; +import com.petrolpark.destroy.compat.jei.render.MoleculeBatchRenderer; import com.petrolpark.destroy.config.DestroyAllConfigs; import com.petrolpark.destroy.core.chemistry.MoleculeDisplayItem; import com.petrolpark.destroy.core.chemistry.MoleculeDisplayItem.MoleculeTooltip; @@ -23,10 +24,12 @@ import mezz.jei.api.ingredients.IIngredientHelper; import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientType; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; import mezz.jei.api.ingredients.subtypes.UidContext; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; @@ -111,14 +114,17 @@ public ItemStack getCheatItemStack(LegacySpecies ingredient) { public static final ResourceLocation FONT_LOCATION = Destroy.asResource("charge"); public static final Style FONT = Style.EMPTY.withFont(FONT_LOCATION); + private final MoleculeBatchRenderer.Cache batchRenderer = new MoleculeBatchRenderer.Cache(); @Override public void render(GuiGraphics graphics, LegacySpecies ingredient) { MoleculeRenderer renderer = ingredient.getRenderer(); + MultiBufferSource.BufferSource buffer = graphics.bufferSource(); PoseStack poseStack = graphics.pose(); poseStack.pushPose(); - renderer.renderItem(0, 0, 16, 16, graphics); + renderer.renderItem(0, 0, 16, 16, poseStack, buffer); + buffer.endBatch(); if(ingredient.getCharge() != 0) { @@ -140,6 +146,11 @@ public void render(GuiGraphics graphics, LegacySpecies ingredient) { //graphics.renderItem(MoleculeDisplayItem.with(ingredient), 0, 0); // TODO check positioning }; + @Override + public void renderBatch(GuiGraphics graphics, List> elements) { + batchRenderer.renderBatch(graphics, elements); + } + @Override public void getTooltip(ITooltipBuilder tooltip, LegacySpecies ingredient, TooltipFlag tooltipFlag) { tooltip.add(ingredient.getName(DestroyAllConfigs.CLIENT.chemistry.iupacNames.get())); diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/render/MoleculeBatchRenderer.java b/src/main/java/com/petrolpark/destroy/compat/jei/render/MoleculeBatchRenderer.java new file mode 100644 index 000000000..4e52849e4 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/compat/jei/render/MoleculeBatchRenderer.java @@ -0,0 +1,94 @@ +package com.petrolpark.destroy.compat.jei.render; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.mojang.blaze3d.vertex.PoseStack; +import com.petrolpark.destroy.Destroy; +import com.petrolpark.destroy.chemistry.legacy.LegacySpecies; +import com.petrolpark.destroy.core.chemistry.MoleculeRenderer; +import mezz.jei.api.ingredients.rendering.BatchRenderElement; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.network.chat.Style; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; + +import java.util.ArrayList; +import java.util.List; + +public class MoleculeBatchRenderer { + + private final List molecules; + private final List moleculesWithCharge; + + public static final ResourceLocation FONT_LOCATION = Destroy.asResource("charge"); + public static final Style FONT = Style.EMPTY.withFont(FONT_LOCATION); + + public MoleculeBatchRenderer(Minecraft minecraft, List> elements) { + molecules = new ArrayList<>(); + moleculesWithCharge = new ArrayList<>(); + + for (BatchRenderElement element : elements) { + int charge = element.ingredient().getCharge(); + FormattedCharSequence chargeStr = null; + if (charge != 0) + { + String s = charge > 0 ? "+" : "-"; + if (Math.abs(charge) > 1) + s = Math.abs(charge) + s; + chargeStr = FormattedCharSequence.forward(s, FONT); + } + + BatchedMolecule m = new BatchedMolecule(element.ingredient().getRenderer(), element.x(), element.y(), chargeStr); + molecules.add(m); + if(chargeStr != null) moleculesWithCharge.add(m); + } + } + + public void render(GuiGraphics graphics, Minecraft minecraft) { + PoseStack poseStack = graphics.pose(); + poseStack.pushPose(); + + MultiBufferSource.BufferSource buffer = graphics.bufferSource(); + for (BatchedMolecule mol : molecules) { + MoleculeRenderer renderer = mol.renderer; + renderer.renderItem(mol.x, mol.y, 16, 16, poseStack, buffer); + } + buffer.endBatch(); + + for (BatchedMolecule mol : moleculesWithCharge) { + poseStack.pushPose(); + poseStack.translate(mol.x, mol.y, 100); + Font fontRenderer = Minecraft.getInstance().font; + graphics.drawString(fontRenderer, mol.charge, -1, -1, 0xFFFFFF, true); + poseStack.popPose(); + } + + poseStack.popPose(); + } + + private record BatchedMolecule(MoleculeRenderer renderer, int x, int y, FormattedCharSequence charge) {} + + public static class Cache { + private final LoadingCache>, MoleculeBatchRenderer> cache = + CacheBuilder.newBuilder() + .maximumSize(6) + .build(new CacheLoader<>() { + @Override + public MoleculeBatchRenderer load(List> elements) { + Minecraft minecraft = Minecraft.getInstance(); + return new MoleculeBatchRenderer(minecraft, elements); + } + }); + + public void renderBatch(GuiGraphics guiGraphics, List> elements) { + MoleculeBatchRenderer batchData = cache.getUnchecked(elements); + + Minecraft minecraft = Minecraft.getInstance(); + batchData.render(guiGraphics, minecraft); + } + } +} diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java index 50c8a2411..0e2d97944 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/MoleculeRenderer.java @@ -1,25 +1,29 @@ package com.petrolpark.destroy.core.chemistry; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; import com.jozufozu.flywheel.core.model.ModelUtil; +import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.vertex.*; import com.mojang.math.Axis; -import com.petrolpark.destroy.Destroy; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Sheets; +import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.AABB; +import net.minecraftforge.client.RenderTypeGroup; +import net.minecraftforge.client.model.IModelBuilder; +import net.minecraftforge.client.model.pipeline.QuadBakingVertexConsumer; +import net.minecraftforge.client.textures.UnitTextureAtlasSprite; import org.joml.Math; import org.joml.Quaternionf; @@ -50,7 +54,8 @@ public class MoleculeRenderer { protected static final double SCALE = 23d; protected static final double BOND_LENGTH = SCALE / 2; - protected SuperByteBuffer model; + //protected SuperByteBuffer model; + protected BakedModel model; /** * The list of Atoms and Bonds to render, and their locations. @@ -126,16 +131,15 @@ public MoleculeRenderer(LegacySpecies molecule) { bb = bb.minmax(new AABB(pair.getFirst(), pair.getFirst())); }; - // Bake all rendered objects into a single buffer - BufferBuilder builder = new BufferBuilder(512); - builder.begin(VertexFormat.Mode.QUADS, RenderType.translucent().format()); + // Bake all rendered objects into a single model + IModelBuilder builder = IModelBuilder.of(false, true, true, ItemTransforms.NO_TRANSFORMS, ItemOverrides.EMPTY, + UnitTextureAtlasSprite.INSTANCE, RenderTypeGroup.EMPTY); + QuadBakingVertexConsumer buffer = new QuadBakingVertexConsumer(builder::addUnculledFace); + buffer.setTintIndex(-1); for (Pair pair : RENDERED_OBJECTS) { - pair.getSecond().renderInto(builder, pair.getFirst()); + pair.getSecond().renderInto(buffer, pair.getFirst()); }; - - BufferBuilder.RenderedBuffer renderedBuffer = builder.end(); - model = new SuperByteBuffer(renderedBuffer.vertexBuffer(), renderedBuffer.drawState()); - renderedBuffer.release(); + model = builder.build(); }; public int getWidth() { @@ -156,26 +160,19 @@ public void render(int xPosition, int yPosition, GuiGraphics graphics) { poseStack.translate(center.x - bb.minX + xPosition, center.y - bb.minY + yPosition, -200); poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); poseStack.translate(-center.x, -center.y, -center.z); -/* - for (Pair pair : RENDERED_OBJECTS) { - pair.getSecond().render(graphics, pair.getFirst()); - }; -*/ - Minecraft mc = Minecraft.getInstance(); - MultiBufferSource.BufferSource buffer = mc.renderBuffers() - .bufferSource(); - RenderType renderType = RenderType.translucent(); + UIRenderHelper.flipForGuiRender(poseStack); - model.renderInto(poseStack, buffer.getBuffer(renderType)); - buffer.endBatch(); + Lighting.setupFor3DItems(); + Minecraft.getInstance().getItemRenderer().renderModelLists(model, ItemStack.EMPTY, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, + poseStack, graphics.bufferSource().getBuffer(Sheets.cutoutBlockSheet())); + graphics.flush(); poseStack.popPose(); }; - public void renderItem(int xPosition, int yPosition, int width, int height, GuiGraphics graphics) { + public void renderItem(int xPosition, int yPosition, int width, int height, PoseStack poseStack, MultiBufferSource.BufferSource buffer) { float scale = java.lang.Math.min(0.5f, java.lang.Math.min((width+2)/(getWidth()+1f), (height+2)/(getHeight()+1f))); - PoseStack poseStack = graphics.pose(); poseStack.pushPose(); Vec3 center = bb.getCenter(); poseStack.translate(xPosition + width/2, yPosition + height/2, 50); @@ -183,18 +180,11 @@ public void renderItem(int xPosition, int yPosition, int width, int height, GuiG poseStack.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime())); poseStack.scale(scale, scale, scale); poseStack.translate(-center.x, -center.y, -center.z); -/* - for (Pair pair : RENDERED_OBJECTS) { - pair.getSecond().render(graphics, pair.getFirst()); - }; -*/ - Minecraft mc = Minecraft.getInstance(); - MultiBufferSource.BufferSource buffer = mc.renderBuffers() - .bufferSource(); - RenderType renderType = RenderType.solid(); + UIRenderHelper.flipForGuiRender(poseStack); - model.renderInto(poseStack, buffer.getBuffer(renderType)); - buffer.endBatch(); + Lighting.setupFor3DItems(); + Minecraft.getInstance().getItemRenderer().renderModelLists(model, ItemStack.EMPTY, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, + poseStack, buffer.getBuffer(Sheets.cutoutBlockSheet())); poseStack.popPose(); }; @@ -440,7 +430,7 @@ public void renderInto(VertexConsumer builder, Vec3 location) { Minecraft.getInstance().getBlockRenderer().getModelRenderer() .renderModel(poseStack.last(), builder, Blocks.AIR.defaultBlockState(), type().getPartial().get(), 1, 1, 1, - LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, null); + 0, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, RenderType.solid()); }; }; @@ -467,7 +457,7 @@ public void renderInto(VertexConsumer builder, Vec3 location) { Minecraft.getInstance().getBlockRenderer().getModelRenderer() .renderModel(poseStack.last(), builder, Blocks.AIR.defaultBlockState(), atom.getPartial().get(), 1, 1, 1, - LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, null); + 0, OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, RenderType.solid()); }; }; }; From 5ea46203eaf3a7401ecb7151cc93e35cbb622d0e Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 30 Mar 2025 16:45:15 +0200 Subject: [PATCH 42/56] =?UTF-8?q?=F0=9F=96=8C=EF=B8=8F=20More=20visual=20n?= =?UTF-8?q?itpicking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed the 3D structure of octasulfur (idk this looks better to me and seems to be more accurate) - Fixed glassblowing recipes rendering with inverted normals in JEI - Slightly inflated the appearance of molten glass when glassblowing to prevent Z-fighting - Fixed some recipe animations in JEI getting broken by a previous update - Fixed Tappers swinging in the wrong direction when placed at certain angles while instanced rendering is enabled --- .../legacy/index/DestroyTopologies.java | 4 +-- .../jei/animation/AnimatedBlowpipe.java | 8 +++++- .../compat/jei/animation/AnimatedSieve.java | 6 ++-- .../compat/jei/animation/AnimatedTreeTap.java | 3 +- .../BlowpipeBlockEntityRenderer.java | 2 +- .../sieve/MechanicalSieveRenderer.java | 2 +- .../processing/treetap/TreeTapInstance.java | 28 +++++++++++-------- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyTopologies.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyTopologies.java index 2778e8b1e..7877defbd 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyTopologies.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyTopologies.java @@ -221,13 +221,13 @@ public class DestroyTopologies { .atom(LegacyElement.SULFUR, new Vec3(0d, 1.5d, 0d)) // 2 .withBondTo(1, BondType.SINGLE) .attach() - .atom(LegacyElement.SULFUR, new Vec3(0.75d, 1.25d, 0.6124d)) // 3 + .atom(LegacyElement.SULFUR, new Vec3(0.75d, 1.75d, 0.6124d)) // 3 .withBondTo(2, BondType.SINGLE) .attach() .atom(LegacyElement.SULFUR, new Vec3(1.5d, 1.5d, 0d)) // 4 .withBondTo(3, BondType.SINGLE) .attach() - .atom(LegacyElement.SULFUR, new Vec3(1.25d, 0.75d, 0.6124d)) // 5 + .atom(LegacyElement.SULFUR, new Vec3(1.75d, 0.75d, 0.6124d)) // 5 .withBondTo(4, BondType.SINGLE) .attach() .atom(LegacyElement.SULFUR, new Vec3(1.5d, 0d, 0d)) // 6 diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedBlowpipe.java b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedBlowpipe.java index 37c4264c0..e5ddd3053 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedBlowpipe.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedBlowpipe.java @@ -1,6 +1,7 @@ package com.petrolpark.destroy.compat.jei.animation; import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.petrolpark.destroy.DestroyBlocks; @@ -8,9 +9,11 @@ import com.petrolpark.destroy.content.processing.glassblowing.BlowpipeBlockEntityRenderer; import com.petrolpark.destroy.content.processing.glassblowing.GlassblowingRecipe; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; +import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.Direction; import net.minecraft.util.Brightness; @@ -38,7 +41,10 @@ public void draw(GlassblowingRecipe recipe, FluidStack fluid, GuiGraphics graphi .rotateY(180d) .translate(-0.5d, -0.5d, 0d); ms.pushPose(); - BlowpipeBlockEntityRenderer.render(recipe, fluid, Math.min((AnimationTickHolder.getRenderTime() % 120f) / 100f, 1f), ms, graphics.bufferSource(), Brightness.FULL_BRIGHT.pack(), OverlayTexture.NO_OVERLAY); + UIRenderHelper.flipForGuiRender(ms); + RenderSystem.disableDepthTest(); + BlowpipeBlockEntityRenderer.render(recipe, fluid, Math.min((AnimationTickHolder.getRenderTime() % 120f) / 100f, 1f), ms, graphics.bufferSource(), LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); + RenderSystem.enableDepthTest(); ms.popPose(); ms.popPose(); diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedSieve.java b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedSieve.java index a4f95e2a6..08fa08441 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedSieve.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedSieve.java @@ -24,9 +24,9 @@ public void draw(GuiGraphics graphics, int xOffset, int yOffset) { ms.pushPose(); TransformStack.cast(ms) .translate(0d, -0.5d, 0.5d) - .rotateZ(90) - .rotateY(getCurrentAngle()) - .translateBack(0.5d, 0d, 0.5d); + .rotateY(90) + .rotateZ(getCurrentAngle()) + .translateBack(0.5d, -0.5d, 0d); blockElement(DestroyPartials.MECHANICAL_SIEVE_SHAFT) .render(graphics); ms.popPose(); diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedTreeTap.java b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedTreeTap.java index 6cea73260..a7ab520bd 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedTreeTap.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/animation/AnimatedTreeTap.java @@ -25,8 +25,7 @@ public void draw(GuiGraphics graphics, int xOffset, int yOffset) { blockElement(DestroyPartials.TREE_TAP_ARM) .rotateBlock(9f * Mth.sin(AnimationTickHolder.getRenderTime() / 4f), 0, 0) - .withRotationOffset(new Vec3(0, -4 / 16f, -1 / 16f)) - .atLocal(0f, - 12 / 16f, 7 / 16f) + .withRotationOffset(new Vec3(0, 0.5, 0.5)) .scale(scale) .render(graphics); diff --git a/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeBlockEntityRenderer.java b/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeBlockEntityRenderer.java index a9e489997..50b1dca48 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeBlockEntityRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/glassblowing/BlowpipeBlockEntityRenderer.java @@ -73,7 +73,7 @@ public static void render(GlassblowingRecipe recipe, FluidStack fluid, float pro }; for (int j = 0; j < shapes; j++) { - DestroyFluidRenderer.renderFluidBoxWithAlpha(fluid, - radii[j], -radii[j], ends[j] - 1/ 128f, radii[j], radii[j], ends[j+1] + 1 / 128f, buffer, ms, light, fluidOpacity); + DestroyFluidRenderer.renderFluidBoxWithAlpha(fluid, - radii[j] - 1/ 512f, -radii[j] - 1/ 128f, ends[j] - 1/ 512f, radii[j] + 1 / 512f, radii[j] + 1 / 128f, ends[j+1] + 1 / 512f, buffer, ms, light, fluidOpacity); }; }; diff --git a/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java index 954ac66af..8b4c2a2d3 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/sieve/MechanicalSieveRenderer.java @@ -59,7 +59,7 @@ protected void renderSafe(MechanicalSieveBlockEntity be, float partialTicks, Pos @Override protected SuperByteBuffer getRotatedModel(MechanicalSieveBlockEntity be, BlockState state) { - return CachedBufferer.partialFacingVertical(DestroyPartials.MECHANICAL_SIEVE_SHAFT, state, state.getValue(MechanicalSieveBlock.X) ? Direction.EAST : Direction.SOUTH); + return CachedBufferer.partialFacing(DestroyPartials.MECHANICAL_SIEVE_SHAFT, state, state.getValue(MechanicalSieveBlock.X) ? Direction.EAST : Direction.SOUTH); }; }; diff --git a/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java index ea0f04f54..f02998c6a 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/treetap/TreeTapInstance.java @@ -2,10 +2,14 @@ import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.petrolpark.destroy.client.DestroyPartials; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.content.kinetics.base.ShaftInstance; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import org.joml.Quaternionf; @@ -15,15 +19,15 @@ public class TreeTapInstance extends ShaftInstance implements DynamicInstance { - final Direction facing; - protected final OrientedData arm; + protected final ModelData arm; public TreeTapInstance(MaterialManager materialManager, TreeTapBlockEntity blockEntity) { super(materialManager, blockEntity); - facing = blockState.getValue(HORIZONTAL_FACING); - arm = getOrientedMaterial().getModel(DestroyPartials.TREE_TAP_ARM, blockState, facing).createInstance() - .setPivot(0.5f, 0.5f, 0.5f); + arm = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(DestroyPartials.TREE_TAP_ARM, blockState) + .createInstance(); updateAnimation(); } @@ -46,11 +50,13 @@ public void remove() { } private void updateAnimation() { - float angle = 9f * Mth.sin((float)Math.toRadians((AnimationTickHolder.getRenderTime() * blockEntity.getSpeed() * 3f / 10) % 360)); - - Vector3f axis = facing.getCounterClockWise().step(); - - arm.setPosition(getInstancePosition()) - .setRotation(new Quaternionf().rotationAxis((float)Math.toRadians(angle), axis)); + Direction facing = blockState.getValue(TreeTapBlock.HORIZONTAL_FACING); + + arm.loadIdentity() + .translate(getInstancePosition()) + .centre() + .rotate(9f * Mth.sin(KineticBlockEntityRenderer.getAngleForTe(blockEntity, blockEntity.getBlockPos(), facing.getClockWise().getAxis())), facing.getClockWise().getAxis()) + .rotateToFace(facing.getOpposite()) + .unCentre(); } } From 3a5d2341a473d55453a019d9c8b7a29b3c9d77f6 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sun, 30 Mar 2025 18:50:50 +0200 Subject: [PATCH 43/56] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=A4=9D?= =?UTF-8?q?=E2=80=8D=F0=9F=A7=91=20Community=20Edition=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed fog flickering caused by smog - Fixed modded fluids not being able to apply their custom fog - Fixed Vats sometimes duplicating inserted items --- .../petrolpark/destroy/client/FogHandler.java | 34 +++++++++++++++---- .../vat/VatControllerBlockEntity.java | 10 +++--- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/client/FogHandler.java b/src/main/java/com/petrolpark/destroy/client/FogHandler.java index 7490508cb..883ddf115 100644 --- a/src/main/java/com/petrolpark/destroy/client/FogHandler.java +++ b/src/main/java/com/petrolpark/destroy/client/FogHandler.java @@ -10,7 +10,9 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; +import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FogType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -26,8 +28,8 @@ public class FogHandler { private static final Color BROWN = new Color(0xFF4D2F19); - protected Color targetColor = new Color(0x00FFFFFF); - protected Color lastColor = new Color(0x00FFFFFF); + protected Color targetColor = Color.BLACK; + protected Color lastColor = Color.TRANSPARENT_BLACK; protected LerpedFloat colorMix = LerpedFloat.linear(); public void tick() { @@ -35,9 +37,13 @@ public void tick() { if (colorMix.getValue() >= 1d) lastColor = targetColor; }; - public void setTargetColor(Color color) { + public void setTargetColor(Color color, float partialTicks) { if (color.equals(targetColor)) return; - lastColor = Color.mixColors(lastColor, targetColor, colorMix.getValue()); + if (lastColor.equals(Color.TRANSPARENT_BLACK)) { + lastColor = color; + } else { + lastColor = getColor(partialTicks); + } targetColor = color; colorMix.setValue(0d); colorMix.chase(1d, 0.2d, Chaser.EXP); @@ -56,13 +62,26 @@ public static void onTick(TickEvent.ClientTickEvent event) { if (event.phase == TickEvent.Phase.START) DestroyClient.FOG_HANDLER.tick(); }; + /** + * {@link Camera#getFluidInCamera()} doesn't account for modded fluids so we need a more general check. + */ + private static FogType getFluidInCamera(Camera camera) { + Minecraft mc = Minecraft.getInstance(); + FluidState state = mc.level.getFluidState(camera.getBlockPosition()); + if (camera.getPosition().y < (double)((float)camera.getBlockPosition().getY() + state.getHeight(mc.level, camera.getBlockPosition()))) { + return FogType.WATER; + } + return camera.getFluidInCamera(); + }; + /** * Render fog according to the world's Smog Level. */ @SubscribeEvent public static void renderFog(RenderFog event) { if (!smogEnabled()) return; - if (event.getType() == FogType.NONE) { + + if (getFluidInCamera(event.getCamera()) == FogType.NONE) { Minecraft mc = Minecraft.getInstance(); float smog = (float)PollutionHelper.getPollution(mc.level, mc.player.blockPosition(), PollutionType.SMOG); event.scaleNearPlaneDistance(1f - (0.8f * smog / (float)PollutionType.SMOG.max)); @@ -77,11 +96,12 @@ public static void renderFog(RenderFog event) { @SubscribeEvent public static void colorFog(ComputeFogColor event) { if (!smogEnabled()) return; - if (event.getCamera().getFluidInCamera() == FogType.NONE) { + + if (getFluidInCamera(event.getCamera()) == FogType.NONE) { Minecraft mc = Minecraft.getInstance(); float smog = (float)PollutionHelper.getPollution(mc.level, mc.player.blockPosition(), PollutionType.SMOG); Color existing = new Color(event.getRed(), event.getGreen(), event.getBlue(), 1f); - DestroyClient.FOG_HANDLER.setTargetColor(Color.mixColors(existing, BROWN, 0.8f * smog / (float)PollutionType.SMOG.max)); + DestroyClient.FOG_HANDLER.setTargetColor(Color.mixColors(existing, BROWN, 0.8f * smog / (float)PollutionType.SMOG.max), AnimationTickHolder.getPartialTicks()); Color color = DestroyClient.FOG_HANDLER.getColor(AnimationTickHolder.getPartialTicks()); event.setRed(color.getRedAsFloat()); event.setGreen(color.getGreenAsFloat()); diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 681a6aebd..b70c785a1 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -231,12 +231,12 @@ public void tick() { cachedMixture.reactForTick(context, getSimulationLevel()); shouldUpdateFluidMixture = true; - if (!cachedMixture.isAtEquilibrium()) advancementBehaviour.awardDestroyAdvancement(DestroyAdvancementTrigger.USE_VAT); - }; + // Put all Items back in the Inventory + for (ItemStack itemStack : availableItemStacks) { + ItemHandlerHelper.insertItemStacked(inventory, itemStack, false); + }; - // Put all Items back in the Inventory - for (ItemStack itemStack : availableItemStacks) { - ItemHandlerHelper.insertItemStacked(inventory, itemStack, false); + if (!cachedMixture.isAtEquilibrium()) advancementBehaviour.awardDestroyAdvancement(DestroyAdvancementTrigger.USE_VAT); }; if (shouldUpdateFluidMixture) { From 85ada740715a931f054c764c7736364079cb5e36 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 31 Mar 2025 02:17:58 +0200 Subject: [PATCH 44/56] =?UTF-8?q?=F0=9F=94=A5=20Heat=20buffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../destroy/chemistry/legacy/LegacyMixture.java | 13 ++++++++++--- .../com/petrolpark/destroy/client/DestroyLang.java | 2 +- .../processing/cooler/CoolerBlockEntity.java | 6 ++++-- .../chemistry/vat/VatControllerBlockEntity.java | 9 +++++++-- .../vat_materials/borosilicate_glass.json | 2 +- .../destroy_compat/vat_materials/copper_casing.json | 2 +- .../destroy_compat/vat_materials/fiberglass.json | 2 +- .../vat_materials/insulated_stainless_steel.json | 2 +- .../destroy/destroy_compat/vat_materials/iron.json | 2 +- .../vat_materials/netherite_block.json | 2 +- .../vat_materials/stainless_steel.json | 2 +- .../destroy_compat/vat_materials/tinted_glass.json | 2 +- .../destroy_compat/vat_materials/weak_glass.json | 2 +- 13 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java index bbcbaea2a..5f6daacb9 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java @@ -408,7 +408,14 @@ public void reactForTick(ReactionContext context, int cycles) { * @param energy In joules per bucket */ public void heat(float energyDensity) { - float volumetricHeatCapacity = getVolumetricHeatCapacity(); + heat(energyDensity, getVolumetricHeatCapacity()); + }; + + public void heatWithBuffer(float energyDensity, float volume, float bufferVolumetricHeatCapacity, float bufferVolume) { + heat(energyDensity, (getVolumetricHeatCapacity() * volume + bufferVolumetricHeatCapacity * bufferVolume) / (volume + bufferVolume)); + }; + + public void heat(float energyDensity, float volumetricHeatCapacity) { if (volumetricHeatCapacity == 0f) return; float temperatureChange = energyDensity / volumetricHeatCapacity; // The theoretical temperature change if no boiling or condensation occurs @@ -420,7 +427,7 @@ public void heat(float energyDensity) { temperatureChange = nextHigherBoilingPoint.getFirst() - temperature; // Only increase the temperature by enough to get to the next BP temperature += temperatureChange; // Raise the Mixture to the boiling point - energyDensity -= temperatureChange * getVolumetricHeatCapacity(); // Energy leftover once the Mixture has been raised to the boiling point + energyDensity -= temperatureChange * volumetricHeatCapacity; // Energy leftover once the Mixture has been raised to the boiling point LegacySpecies molecule = nextHigherBoilingPoint.getSecond(); float liquidConcentration = getConcentrationOf(molecule) * (1f - states.get(molecule)); // The moles per bucket of liquid Molecules @@ -448,7 +455,7 @@ public void heat(float energyDensity) { temperatureChange = nextLowerBoilingPoint.getFirst() - temperature; // Only decrease the temperature by enough to get to the next condensation point temperature += temperatureChange; // Decrease the Mixture to the boiling point - energyDensity -= temperatureChange * getVolumetricHeatCapacity(); // Additional energy once the Mixture has been lowered to the condensation point + energyDensity -= temperatureChange * volumetricHeatCapacity; // Additional energy once the Mixture has been lowered to the condensation point LegacySpecies molecule = nextLowerBoilingPoint.getSecond(); float gasConcentration = getConcentrationOf(molecule) * states.get(molecule); diff --git a/src/main/java/com/petrolpark/destroy/client/DestroyLang.java b/src/main/java/com/petrolpark/destroy/client/DestroyLang.java index 56f78b360..b59a4244e 100644 --- a/src/main/java/com/petrolpark/destroy/client/DestroyLang.java +++ b/src/main/java/com/petrolpark/destroy/client/DestroyLang.java @@ -172,7 +172,7 @@ public static List mixtureIngredientTooltip(CompoundTag fluidTag) { }; private static final float pressureMin = 0f; - private static final float pressureMax = 1000000f; + private static final float pressureMax = 4000000f; private static final float conductivityMin = 0f; private static final float conductivityMax = 100f; diff --git a/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java b/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java index 6fc238a96..eb8739661 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java @@ -49,6 +49,8 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import com.petrolpark.destroy.chemistry.api.util.Constants; + public class CoolerBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { private static final int TANK_CAPACITY = 1000; @@ -99,7 +101,7 @@ private void consumeFluid() { totalMolesPerBucket += concentration; if (molecule.hasTag(DestroyMolecules.Tags.REFRIGERANT)) { totalRefrigerantMolesPerBucket += concentration; - coolingPower += DestroyAllConfigs.SERVER.blocks.coolerEfficiency.getF() * concentration * amount * molecule.getMolarHeatCapacity() / 100; + coolingPower += DestroyAllConfigs.SERVER.blocks.coolerEfficiency.getF() * concentration * amount * molecule.getMolarHeatCapacity() * 10 / Constants.MILLIBUCKETS_PER_LITER; }; }; @@ -107,7 +109,7 @@ private void consumeFluid() { } else if (fluidStack.getFluid().is(Fluids.COOLANT.tag)) { - coolingPower += fluidStack.getAmount(); // One bucket of coolant = 50 seconds of coling + coolingPower += fluidStack.getAmount(); // One bucket of coolant = 50 seconds of cooling } if (coolingPower > 0f) { diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index b70c785a1..e6161bdc9 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -193,17 +193,22 @@ public void tick() { boolean shouldUpdateFluidMixture = false; Vat vat = getVatOptional().get(); if (tankBehaviour.isEmpty()) return; - double fluidAmount = getCapacity() / Constants.MILLIBUCKETS_PER_LITER; // Converts getFluidAmount() in mB to liters + float fluidAmount = (float)getCapacity() / Constants.MILLIBUCKETS_PER_LITER; // Converts getFluidAmount() in mB to liters int cyclesPerTick = getSimulationLevel(); // Heating for (int cycle = 0; cycle < cyclesPerTick; cycle++) { float energyChange = heatingPower; + + // Treat the walls of the Vat like an additional volume of material with its own heat capacity + float vatSideVolume = vat.getSideBlockPositions().size() * 1000f / Constants.MILLIBUCKETS_PER_LITER; + float vatSideHeatCapacity = 3000f; + energyChange += (Pollution.getLocalTemperature(getLevel(), getBlockPos()) - cachedMixture.getTemperature()) * vat.getConductance(); // Fourier's Law (sort of), the divide by 20 is for 20 ticks per second energyChange /= 20 * cyclesPerTick; if (Math.abs(energyChange / (fluidAmount * cachedMixture.getVolumetricHeatCapacity())) > 0.001f && fluidAmount != 0d) { // Only bother heating if the temperature change will be somewhat significant - cachedMixture.heat(energyChange / (float)fluidAmount); + cachedMixture.heatWithBuffer(energyChange / fluidAmount, fluidAmount, vatSideHeatCapacity, vatSideVolume); cachedMixture.disturbEquilibrium(); } else { break; diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/borosilicate_glass.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/borosilicate_glass.json index 3ab2fa116..b7ce57f7c 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/borosilicate_glass.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/borosilicate_glass.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 300000, + "max_pressure_difference": 1200000, "conductivity": 15, "transparent": true, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/copper_casing.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/copper_casing.json index 5ce450860..f0ef29b79 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/copper_casing.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/copper_casing.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 500000, + "max_pressure_difference": 2000000, "conductivity": 400, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/fiberglass.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/fiberglass.json index b44660147..ba705f70f 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/fiberglass.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/fiberglass.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 350000, + "max_pressure_difference": 1400000, "conductivity": 17, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/insulated_stainless_steel.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/insulated_stainless_steel.json index 571e40c58..28fde0ac1 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/insulated_stainless_steel.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/insulated_stainless_steel.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 800000, + "max_pressure_difference": 3200000, "conductivity": 20, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/iron.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/iron.json index 2dfa31f69..d6f6bb0db 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/iron.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/iron.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 250000, + "max_pressure_difference": 1000000, "conductivity": 50, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/netherite_block.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/netherite_block.json index fb6c2dc7b..2126c56fd 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/netherite_block.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/netherite_block.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 1200000, + "max_pressure_difference": 4800000, "conductivity": 70, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/stainless_steel.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/stainless_steel.json index aafee6572..c88839723 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/stainless_steel.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/stainless_steel.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 1000000, + "max_pressure_difference": 4000000, "conductivity": 35, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/tinted_glass.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/tinted_glass.json index 345148708..f9136bd0d 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/tinted_glass.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/tinted_glass.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 100000, + "max_pressure_difference": 400000, "conductivity": 18, "transparent": false, "blocks": [ diff --git a/src/main/resources/data/destroy/destroy_compat/vat_materials/weak_glass.json b/src/main/resources/data/destroy/destroy_compat/vat_materials/weak_glass.json index 07a742fdf..f258c4fdc 100644 --- a/src/main/resources/data/destroy/destroy_compat/vat_materials/weak_glass.json +++ b/src/main/resources/data/destroy/destroy_compat/vat_materials/weak_glass.json @@ -1,5 +1,5 @@ { - "max_pressure_difference": 100000, + "max_pressure_difference": 400000, "conductivity": 30, "transparent": true, "blocks": [ From 299fbb0026f05c4bd24c39eadbe14696ea8c9c9e Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 31 Mar 2025 02:32:16 +0200 Subject: [PATCH 45/56] =?UTF-8?q?=E2=9D=84=EF=B8=8F=20Coolers=20cool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed cooler efficiency being 1000 times lower than it should be, causing most coolants to last only 1 game tick --- .../destroy/content/processing/cooler/CoolerBlockEntity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java b/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java index 6fc238a96..1b2e70957 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/cooler/CoolerBlockEntity.java @@ -2,6 +2,7 @@ import java.util.List; +import com.petrolpark.destroy.chemistry.api.util.Constants; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -99,7 +100,7 @@ private void consumeFluid() { totalMolesPerBucket += concentration; if (molecule.hasTag(DestroyMolecules.Tags.REFRIGERANT)) { totalRefrigerantMolesPerBucket += concentration; - coolingPower += DestroyAllConfigs.SERVER.blocks.coolerEfficiency.getF() * concentration * amount * molecule.getMolarHeatCapacity() / 100; + coolingPower += DestroyAllConfigs.SERVER.blocks.coolerEfficiency.getF() * concentration * amount * molecule.getMolarHeatCapacity() * 10 / Constants.MILLIBUCKETS_PER_LITER; }; }; From 9bb679bde5305d961b8dd694328c1c391d61b5a4 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 31 Mar 2025 04:01:50 +0200 Subject: [PATCH 46/56] =?UTF-8?q?=F0=9F=90=95=20wow=20so=20cool=20much=20o?= =?UTF-8?q?riginal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit will anyone actually get to enjoy this before Create 6 compatibility is done? --- README.md | 17 ++++++++--------- build.gradle | 6 +++--- gradle.properties | 2 +- .../resources/assets/destroy/lang/en_us.json | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 005dddd8d..7d1550dcb 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ -# Destroy +# Destroy - Snapshot 𝑖 -Destroy is a chemistry-themed add-on to the popular Create mod. Right now it's under development. +A modified version of [Destroy](https://modrinth.com/mod/destroy/) that aims to fix several bugs which prevented the automation of many processes in Survival mode. +Comes with a handful of quality of life features, including minor recipe tweaks and better readability when viewing chemical reactions in JEI. -Find out more on the [Discord](https://discord.gg/6EBJ3AzbHu) and [Modrinth](https://modrinth.com/mod/destroy/) page. - -Currently, 1.0 is in development. **This will still be a beta release**. - -# License - -All rights are reserved unless otherwise explicitly stated. +This is currently based on the 0.1.1 version, which is **not** compatible with the latest version of Create! +Make sure you have the following mods installed before running this: +- [Create 0.5.1j](https://modrinth.com/mod/create/version/1.20.1-0.5.1.j) +- [Petrolpark's Library 1.4.2](https://modrinth.com/mod/petrolpark/version/1.20.1-1.4.2) +If you run into any issues, please report them here, not on the main Destroy GitHub page. Thank you! \ No newline at end of file diff --git a/build.gradle b/build.gradle index 05fd97cfc..820759178 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ afterEvaluate { tasks.configureReobfTaskForReobfJarJar.mustRunAfter(tasks.compileJava) } -// Mod Detailss +// Mod Details version = "${mod_version}" group = 'com.petrolpark.destroy' archivesBaseName = "destroy-${minecraft_version}" @@ -217,7 +217,7 @@ dependencies { // JEI compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}") compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") - implementation fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") + runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") // Farmer's Delight compileOnly fg.deobf("curse.maven:farmers-delight-398521:${farmersdelight_version}") @@ -227,7 +227,7 @@ dependencies { runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${minecraft_version}") // TFMG - implementation fg.deobf("curse.maven:create-industry-693815:5558101") + compileOnly fg.deobf("curse.maven:create-industry-693815:5558101") // CBC implementation fg.deobf("com.rbasamoyai:ritchiesprojectilelib:1.0.0-369e88d+1.20.1-forge") diff --git a/gradle.properties b/gradle.properties index b75b0b4fa..e2dc43119 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G org.gradle.daemon = false # Destroy info -mod_version = 0.1.1 +mod_version = 0.1.1-snapshot-i+0 minecraft_version = 1.20.1 forge_version = 47.3.7 diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index b11439730..18aaf69fb 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -1174,7 +1174,7 @@ "destroy.reaction.hydrogen_combustion": "[destroy:hydrogen] Combustion", "destroy.reaction.hydrogen_combustion.description": "The highly {exothermic, destroy:exothermic} {oxidation, destroy:oxidation} of [destroy:hydrogen].", "destroy.reaction.hydrogen_cyanide_dissociation": "[destroy:hydrogen_cyanide] Dissociation", - "destroy.reaction.hydrogen_cyanide_dissociation.description": "Hydrogen cyanide is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", + "destroy.reaction.hydrogen_cyanide_dissociation.description": "[destroy:hydrogen_cyanide] is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.hydrogen_iodide_synthesis": "[destroy:hydrogen_iodide] Synthesis", "destroy.reaction.hydrogen_iodide_synthesis.description": "A method for the production of [destroy:hydrogen_iodide].", "destroy.reaction.hydroxide_neutralization": "Neutralization", @@ -1182,7 +1182,7 @@ "destroy.reaction.hypochlorite_formation": "[destroy:hypochlorite] Formation", "destroy.reaction.hypochlorite_formation.description": "The {disproportionation, destroy:disproportionation} of [destroy:chlorine] with sodium hydroxide.", "destroy.reaction.hypochlorous_acid_dissociation": "[destroy:hypochlorous_acid] Dissociation", - "destroy.reaction.hypochlorous_acid_dissociation.description": "Hypochlorous Acid is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", + "destroy.reaction.hypochlorous_acid_dissociation.description": "[destroy:hypochlorous_acid] is a weak acid that does not easily dissociate in water. It can be coaxed into doing so by reacting it with a {base, destroy:base}.", "destroy.reaction.iodide_displacement": "[destroy:iodide] Displacement", "destroy.reaction.iodide_displacement.description": "The {oxidation, destroy:oxidation} of [destroy:iodide] and {reduction, destroy:reduction} of [destroy:chlorine].", "destroy.reaction.iodine_dissolution": "[destroy:iodine] Solution", From 00f2a6611d40883ef0c7b77252df51e93823f19e Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Tue, 1 Apr 2025 14:34:05 +0200 Subject: [PATCH 47/56] =?UTF-8?q?=F0=9F=8C=8D=20Whoops,=20messed=20up=20de?= =?UTF-8?q?dicated=20servers=20again?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Also removed redundant generic amine molecule and testing a fix for Create's portable storage interfaces getting stuck --- .../legacy/index/DestroyMolecules.java | 7 ---- .../trypolithography/CircuitMaskItem.java | 1 + ...PortableStorageInterfaceMovementMixin.java | 34 +++++++++++++++++++ src/main/resources/destroy.mixins.json | 1 + 4 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/petrolpark/destroy/mixin/PortableStorageInterfaceMovementMixin.java diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyMolecules.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyMolecules.java index eeb4134db..f69ed5e52 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyMolecules.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/index/DestroyMolecules.java @@ -617,13 +617,6 @@ public final class DestroyMolecules { .hypothetical() .translationKey("amide") .build(), - - GENERIC_AMINE = builder() - .id("generic_amine") - .structure(LegacyMolecularStructure.deserialize("destroy:linear:RC(R)(R)N")) - .hypothetical() - .translationKey("amine") - .build(), GENERIC_BORANE = builder() .id("generic_borane") diff --git a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java index 7a3c5a159..6732de738 100644 --- a/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java +++ b/src/main/java/com/petrolpark/destroy/content/processing/trypolithography/CircuitMaskItem.java @@ -95,6 +95,7 @@ public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotI }; @Override + @OnlyIn(Dist.CLIENT) public void appendHoverText(ItemStack stack, Level level, List tooltipComponents, TooltipFlag isAdvanced) { super.appendHoverText(stack, level, tooltipComponents, isAdvanced); if (stack.getOrCreateTag().contains("HideContaminants")) return; diff --git a/src/main/java/com/petrolpark/destroy/mixin/PortableStorageInterfaceMovementMixin.java b/src/main/java/com/petrolpark/destroy/mixin/PortableStorageInterfaceMovementMixin.java new file mode 100644 index 000000000..45b0f3714 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/PortableStorageInterfaceMovementMixin.java @@ -0,0 +1,34 @@ +package com.petrolpark.destroy.mixin; + +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(PortableStorageInterfaceMovement.class) +public class PortableStorageInterfaceMovementMixin { + /** + * This isn't related to Destroy whatsoever but my farms keep getting stuck and + * it's pissing me off so fuck it, I'm doing it here. + */ + @Inject( + method = "Lcom/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement;tick(Lcom/simibubi/create/content/contraptions/behaviour/MovementContext;)V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/nbt/CompoundTag;contains(Ljava/lang/String;)Z", + remap = true + ), + remap = false, + cancellable = true + ) + private void fixStalledInterface(MovementContext context, CallbackInfo ci) { + // If the PSI has no working position set, unstall it. + // I haven't found the actual root cause for this but I suspect it happens when the chunk gets unloaded right before a PSI disengages. + if(!context.data.contains("WorkingPos")) { + ((PortableStorageInterfaceMovement)(Object)this).cancelStall(context); + ci.cancel(); + } + } +} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 0b8b7af49..1edfb5c59 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -53,6 +53,7 @@ "PipeConnectionMixin", "PlayerMixin", "PonderTagScreenMixin", + "PortableStorageInterfaceMovementMixin", "SchematicannonInventoryMixin", "SequencedAssemblyRecipeMixin", "ServerGamePacketListenerImplMixin", From 4c4429ac3181b98c47dfa42259a15579bb719127 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Wed, 2 Apr 2025 04:53:01 +0200 Subject: [PATCH 48/56] =?UTF-8?q?=F0=9F=8C=A1=EF=B8=8F=20Never=20studied?= =?UTF-8?q?=20thermodynamics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Vats now have their own temperature and exchange heat with their contents - Heat and cold sources now act as constant temperature sources instead of energy providers or sinks - Localized heat conductance --- .../chemistry/legacy/LegacyMixture.java | 9 +- .../core/chemistry/vat/IVatHeaterBlock.java | 25 ++++++ .../vat/VatControllerBlockEntity.java | 89 +++++++++++++------ .../chemistry/vat/VatSideBlockEntity.java | 9 +- .../resources/assets/destroy/lang/en_us.json | 3 +- 5 files changed, 91 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java index 5f6daacb9..7cb29c058 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java @@ -408,14 +408,7 @@ public void reactForTick(ReactionContext context, int cycles) { * @param energy In joules per bucket */ public void heat(float energyDensity) { - heat(energyDensity, getVolumetricHeatCapacity()); - }; - - public void heatWithBuffer(float energyDensity, float volume, float bufferVolumetricHeatCapacity, float bufferVolume) { - heat(energyDensity, (getVolumetricHeatCapacity() * volume + bufferVolumetricHeatCapacity * bufferVolume) / (volume + bufferVolume)); - }; - - public void heat(float energyDensity, float volumetricHeatCapacity) { + float volumetricHeatCapacity = getVolumetricHeatCapacity(); if (volumetricHeatCapacity == 0f) return; float temperatureChange = energyDensity / volumetricHeatCapacity; // The theoretical temperature change if no boiling or condensation occurs diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java index 6429afa9e..99644b1bd 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java @@ -48,4 +48,29 @@ public static float getHeatingPower(Level level, BlockPos blockPos, Direction fa return 0f; }; + + static float getTemperatureDifference(Level level, BlockPos blockPos, Direction face) { + BlockState state = level.getBlockState(blockPos); + + if (state.isAir()) return 0f; + + // IVatHeaters + if (state.getBlock() instanceof IVatHeaterBlock heater) { + return heater.getHeatingPower(level, state, blockPos, face); + }; + + // Blaze Burners, Coolers, etc. + if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && face == Direction.UP) { + HeatLevel heatLevel = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); + if (heatLevel == HeatLevel.KINDLED) { + return 500f; + } else if (heatLevel == HeatLevel.SEETHING) { + return 1500f; + } else if ("FROSTING".equals(heatLevel.name())) { + return -500f; + }; + }; + + return 0f; + }; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index e6161bdc9..84bddd7b7 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -10,11 +10,7 @@ import javax.annotation.Nullable; -import com.petrolpark.destroy.DestroyAdvancementTrigger; -import com.petrolpark.destroy.DestroyBlockEntityTypes; -import com.petrolpark.destroy.DestroyBlocks; -import com.petrolpark.destroy.DestroyFluids; -import com.petrolpark.destroy.DestroyRecipeTypes; +import com.petrolpark.destroy.*; import com.petrolpark.destroy.chemistry.api.util.Constants; import com.petrolpark.destroy.chemistry.legacy.LegacyMixture; import com.petrolpark.destroy.chemistry.legacy.LegacyMixture.ReactionContext; @@ -27,6 +23,7 @@ import com.petrolpark.destroy.core.block.entity.ISpecialWhenHoveredBlockEntity; import com.petrolpark.destroy.core.chemistry.MixtureContentsDisplaySource; import com.petrolpark.destroy.core.chemistry.recipe.MixtureConversionRecipe; +import com.petrolpark.destroy.core.chemistry.vat.material.VatMaterial; import com.petrolpark.destroy.core.chemistry.vat.VatFluidTankBehaviour.VatTankSegment.VatFluidTank; import com.petrolpark.destroy.core.chemistry.vat.VatSideBlockEntity.DisplayType; import com.petrolpark.destroy.core.data.advancement.DestroyAdvancementBehaviour; @@ -59,6 +56,7 @@ import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -89,16 +87,14 @@ public class VatControllerBlockEntity extends SmartBlockEntity implements IHaveL * This Mixture belongs to an imaginary Fluid Stack with a size equal to the capacity of the Vat. */ protected LegacyMixture cachedMixture; - /** - * The power (in W) being supplied to this Vat. This can be positive (if the Vat is - * being heated) or negative (if it is being cooled). - */ - protected float heatingPower; + /** * The amount of UV being supplied to this Vat. */ protected float UVPower; + protected float vatTemperature; + /* * As the client side doesn't have access to the cached Mixture, store the pressure, temperature, and whether it is boiling or at equilibrium */ @@ -198,20 +194,41 @@ public void tick() { int cyclesPerTick = getSimulationLevel(); // Heating + int vatSurfaceArea = vat.getSideBlockPositions().size(); + float ambientTemperature = Pollution.getLocalTemperature(getLevel(), getBlockPos()); + float averageTemperature = (float)vat.getSideBlockPositions().stream().mapToDouble(pos -> + getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()) + .map(vatSide -> IVatHeaterBlock.getTemperatureDifference(getLevel(), pos.relative(vatSide.direction), vatSide.direction.getOpposite()) + * VatMaterial.getMaterial(vatSide.getMaterial()).get().thermalConductivity()) + .orElse(0f)).sum(); + averageTemperature = Math.max(0f, ambientTemperature + averageTemperature / vat.getConductance()); + + float vatSideHeatCapacity = 3000f*1000f; // Assume all Vat materials have the same heat capacity for now + float vatConductance = vat.getConductance()*1000f; + + float mixtureConcentration = cachedMixture.getTotalConcentration(); + for (int cycle = 0; cycle < cyclesPerTick; cycle++) { - float energyChange = heatingPower; + // Conduct heat between the Vat's walls and its surroundings + float energyChangeExternal = (averageTemperature - vatTemperature) * vatConductance; // Fourier's Law (sort of), the divide by 20 is for 20 ticks per second + energyChangeExternal /= 20 * cyclesPerTick; - // Treat the walls of the Vat like an additional volume of material with its own heat capacity - float vatSideVolume = vat.getSideBlockPositions().size() * 1000f / Constants.MILLIBUCKETS_PER_LITER; - float vatSideHeatCapacity = 3000f; + // Conduct heat between the Vat's walls and its contents + float energyChangeInternal = (vatTemperature - cachedMixture.getTemperature()) * vatConductance; + energyChangeInternal /= 20 * cyclesPerTick; - energyChange += (Pollution.getLocalTemperature(getLevel(), getBlockPos()) - cachedMixture.getTemperature()) * vat.getConductance(); // Fourier's Law (sort of), the divide by 20 is for 20 ticks per second - energyChange /= 20 * cyclesPerTick; - if (Math.abs(energyChange / (fluidAmount * cachedMixture.getVolumetricHeatCapacity())) > 0.001f && fluidAmount != 0d) { // Only bother heating if the temperature change will be somewhat significant - cachedMixture.heatWithBuffer(energyChange / fluidAmount, fluidAmount, vatSideHeatCapacity, vatSideVolume); + vatTemperature += (energyChangeExternal - energyChangeInternal) / vatSideHeatCapacity; + + // Prevent temperature from exploding to infinity when conductance is very high (e.g. copper vat) + // (can't be bothered to do proper integration this is just a test anyway) + float predictedMixtureTemperatureChange = Math.abs(energyChangeInternal / (fluidAmount * cachedMixture.getVolumetricHeatCapacity())); + if(predictedMixtureTemperatureChange > Math.abs(vatTemperature - cachedMixture.getTemperature())) + energyChangeInternal *= 0.99f * Math.abs(vatTemperature - cachedMixture.getTemperature()) / predictedMixtureTemperatureChange; + + // Only bother heating if the temperature change will be somewhat significant + if (predictedMixtureTemperatureChange > 0.001f && fluidAmount != 0d) { + cachedMixture.heat(energyChangeInternal / fluidAmount); cachedMixture.disturbEquilibrium(); - } else { - break; }; }; @@ -287,9 +304,10 @@ public static int getSimulationLevel() { protected void read(CompoundTag tag, boolean clientPacket) { super.read(tag, clientPacket); - heatingPower = tag.getFloat("HeatingPower"); UVPower = tag.getFloat("UVPower"); + vatTemperature = tag.getFloat("VatTemperature"); + // Vat if (tag.contains("Vat", Tag.TAG_COMPOUND)) { vat = Vat.read(tag.getCompound("Vat"), getBlockPos()); @@ -319,9 +337,10 @@ protected void read(CompoundTag tag, boolean clientPacket) { protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); - tag.putFloat("HeatingPower", heatingPower); tag.putFloat("UVPower", UVPower); + tag.putFloat("VatTemperature", vatTemperature); + // Vat if (vat.isPresent()) { CompoundTag vatTag = new CompoundTag(); @@ -450,6 +469,7 @@ public boolean tryMakeVat() { }); vat = Optional.of(newVat.get()); + vatTemperature = Pollution.getLocalTemperature(getLevel(), getBlockPos()); finalizeVatConstruction(); updateCachedMixture(); flush(); @@ -458,6 +478,20 @@ public boolean tryMakeVat() { return true; }; + public void recomputeVatPower() { + if (!hasLevel() || getLevel().isClientSide() || !vat.isPresent()) return; + + vat.get().getSideBlockPositions().forEach(pos -> { + BlockState state = getLevel().getBlockState(pos); + if (state.is(DestroyBlocks.VAT_CONTROLLER.get())) return; + + getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()).ifPresent(vatSide -> { + BlockPos adjacentPos = pos.relative(vatSide.direction); + vatSide.setPowerFromAdjacentBlock(adjacentPos); + }); + }); + } + private void finalizeVatConstruction() { tankBehaviour.allowExtraction(); // Enable extraction from the Vat now it actually exists tankBehaviour.setCapacity(vat.get().getCapacity()); @@ -501,7 +535,6 @@ public void deleteVat(BlockPos posDestroyed) { }); }; }); - heatingPower = 0f; UVPower = 0f; cachedMixture = new LegacyMixture(); @@ -593,11 +626,6 @@ public float getRenderedFluidLevel(float partialTicks) { } }; - public void changeHeatingPower(float powerChange) { - heatingPower += powerChange; - sendData(); - }; - public void changeUVPower(float UVChange) { UVPower += UVChange; if (cachedMixture != null) cachedMixture.disturbEquilibrium(); @@ -632,6 +660,11 @@ public float getTemperature() { return cachedMixture.getTemperature(); }; + @SuppressWarnings("null") + public float getVatTemperature() { + return vatTemperature; + }; + /** * Get the pressure above room pressure of the gas in this Vat (in Pa). */ diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java index 7b14bbb6f..9a7d8f36d 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java @@ -331,12 +331,6 @@ public void setPowerFromAdjacentBlock(BlockPos heaterOrLampPos) { VatControllerBlockEntity vatController = getController(); if (vatController == null) return; - float newPower = IVatHeaterBlock.getHeatingPower(getLevel(), heaterOrLampPos, direction.getOpposite()); - if (newPower != oldPower) { - vatController.changeHeatingPower(newPower - oldPower); - oldPower = newPower; - }; - float newUVPower = 0f; if (VatMaterial.getMaterial(getMaterial()).map(VatMaterial::transparent).orElse(false)) { newUVPower = IUVLampBlock.getUVPower(getLevel(), heaterOrLampPos, direction.getOpposite()); @@ -521,7 +515,8 @@ public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneak if (getDisplayType().showsTemperature) { TemperatureUnit unit = DestroyAllConfigs.CLIENT.chemistry.temperatureUnit.get(); DestroyLang.translate("tooltip.vat.temperature", unit.of(controller.getTemperature(), df)).style(ChatFormatting.WHITE).forGoggles(tooltip); - if (DestroyAllConfigs.CLIENT.chemistry.nerdMode.get()) DestroyLang.translate("tooltip.vat.power", df.format(controller.heatingPower / 1000f)).forGoggles(tooltip); + DestroyLang.translate("tooltip.vat.temperature.outer", unit.of(controller.getVatTemperature(), df)).style(ChatFormatting.WHITE).forGoggles(tooltip); + //if (DestroyAllConfigs.CLIENT.chemistry.nerdMode.get()) DestroyLang.translate("tooltip.vat.power", df.format(controller.heatingPower / 1000f)).forGoggles(tooltip); } else if (getDisplayType().showsPressure) { Vat vat = getVatOptional().get(); DestroyLang.translate("tooltip.vat.pressure.header").style(ChatFormatting.WHITE).forGoggles(tooltip); diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index 18aaf69fb..fa4b43a69 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -1465,7 +1465,8 @@ "destroy.tooltip.vat.pressure.header": "Vat Pressure:", "destroy.tooltip.vat.pressure.max": "Maximum: %1$skPa (%2$s)", "destroy.tooltip.vat.power": "Power Supplied: %1$skW", - "destroy.tooltip.vat.temperature": "Vat Temperature: %1$s", + "destroy.tooltip.vat.temperature": "Mixture Temperature: %1$s", + "destroy.tooltip.vat.temperature.outer": "Vat Temperature: %1$s", "destroy.tooltip.vat.reacting.header": "Reacting", "destroy.tooltip.vat.reacting": "The Mixture in this Vat is constantly changing. It will be difficult to extract it.", "destroy.tooltip.vat_material.conductivity": "Conductivity:", From 77bcf04732cea00f18235922089462d15b5dc110 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Thu, 3 Apr 2025 15:05:38 +0200 Subject: [PATCH 49/56] =?UTF-8?q?=E2=99=A8=EF=B8=8F=20Finetuning=20and=20c?= =?UTF-8?q?leanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adjusted new heating mechanics - Fixed Vats with a full vacuum not refilling themselves with air when vented --- .../vat/VatControllerBlockEntity.java | 66 +++++++++++++------ .../chemistry/vat/VatFluidTankBehaviour.java | 4 ++ 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 84bddd7b7..484ff1c21 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -194,7 +194,6 @@ public void tick() { int cyclesPerTick = getSimulationLevel(); // Heating - int vatSurfaceArea = vat.getSideBlockPositions().size(); float ambientTemperature = Pollution.getLocalTemperature(getLevel(), getBlockPos()); float averageTemperature = (float)vat.getSideBlockPositions().stream().mapToDouble(pos -> getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()) @@ -203,33 +202,58 @@ public void tick() { .orElse(0f)).sum(); averageTemperature = Math.max(0f, ambientTemperature + averageTemperature / vat.getConductance()); - float vatSideHeatCapacity = 3000f*1000f; // Assume all Vat materials have the same heat capacity for now - float vatConductance = vat.getConductance()*1000f; + int vatSideVolume = vat.getSideBlockPositions().size(); - float mixtureConcentration = cachedMixture.getTotalConcentration(); + // The volumetric heat capacity of one Vat block in joules per bucket-kelvin (1 block = 1 bucket) + // Assume all Vat materials have the same heat capacity for now + float vatSideHeatCapacity = 3000f * 10f; + + // 10 is an arbitrary number and I'm not entirely sure where it's coming from but I find that without it, Vats don't transfer enough energy + // to their liquid contents to raise their temperature within a reasonable amount of time. + // Maybe I missed some important detail, or something's wrong with the way conductance is calculated, or maybe this is completely realistic and it only feels + // weird in game because it's easy to forget you're heating liquid through 1 meter of solid metal. Either way, gameplay before realism. + float vatConductance = vat.getConductance()*10f; + + boolean settled = false; + + for (int cycle = 0; cycle < cyclesPerTick && !settled ; cycle++) { + settled = true; - for (int cycle = 0; cycle < cyclesPerTick; cycle++) { // Conduct heat between the Vat's walls and its surroundings float energyChangeExternal = (averageTemperature - vatTemperature) * vatConductance; // Fourier's Law (sort of), the divide by 20 is for 20 ticks per second energyChangeExternal /= 20 * cyclesPerTick; - // Conduct heat between the Vat's walls and its contents - float energyChangeInternal = (vatTemperature - cachedMixture.getTemperature()) * vatConductance; - energyChangeInternal /= 20 * cyclesPerTick; - - vatTemperature += (energyChangeExternal - energyChangeInternal) / vatSideHeatCapacity; - - // Prevent temperature from exploding to infinity when conductance is very high (e.g. copper vat) - // (can't be bothered to do proper integration this is just a test anyway) - float predictedMixtureTemperatureChange = Math.abs(energyChangeInternal / (fluidAmount * cachedMixture.getVolumetricHeatCapacity())); - if(predictedMixtureTemperatureChange > Math.abs(vatTemperature - cachedMixture.getTemperature())) - energyChangeInternal *= 0.99f * Math.abs(vatTemperature - cachedMixture.getTemperature()) / predictedMixtureTemperatureChange; + float energyChangeInternal = 0f; - // Only bother heating if the temperature change will be somewhat significant - if (predictedMixtureTemperatureChange > 0.001f && fluidAmount != 0d) { - cachedMixture.heat(energyChangeInternal / fluidAmount); - cachedMixture.disturbEquilibrium(); + // Conduct heat between the Vat's walls and its contents + if(fluidAmount > 0d) + { + energyChangeInternal = (vatTemperature - cachedMixture.getTemperature()) * vatConductance; + energyChangeInternal /= 20 * cyclesPerTick; + + // Prevent temperature from exploding to infinity when conductance is very high (e.g. copper vat) + // (can't be bothered to do proper integration this is just a test anyway) + float predictedMixtureTemperatureChange = Math.abs(energyChangeInternal / (fluidAmount * cachedMixture.getVolumetricHeatCapacity())); + float temperatureDifference = Math.abs(vatTemperature - cachedMixture.getTemperature()); + + // Only bother heating if the temperature change will be somewhat significant + if (temperatureDifference > 0.001f || predictedMixtureTemperatureChange > 0.001f) + { + if (predictedMixtureTemperatureChange > temperatureDifference) + energyChangeInternal *= 0.99f * Math.abs(vatTemperature - cachedMixture.getTemperature()) / predictedMixtureTemperatureChange; + + cachedMixture.heat(energyChangeInternal / fluidAmount); + cachedMixture.disturbEquilibrium(); + settled = false; + } }; + + // Temperature change = Energy change / (Volume * Volumetric heat capacity) + float vatTemperatureChange = (energyChangeExternal - energyChangeInternal) / (vatSideVolume * vatSideHeatCapacity); + if (Math.abs(vatTemperatureChange) > 0.001f) { + vatTemperature += vatTemperatureChange; + settled = false; + } }; // Take all Items out of the Inventory @@ -271,7 +295,7 @@ public void tick() { // Releasing gas if there is an open vent VatSideBlockEntity openVent = getOpenVent(); - if (openVent != null && !getGasTank().isEmptyOrFullOfAir()) { + if (openVent != null && !getGasTank().wasFlushed()) { PollutionHelper.pollute(getLevel(), openVent.getBlockPos().relative(openVent.direction), 10, flush()); updateCachedMixture(); }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java index 2a9f453fe..29e595788 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatFluidTankBehaviour.java @@ -254,6 +254,10 @@ public boolean isEmptyOrFullOfAir() { return isEmpty() || flushed; }; + public boolean wasFlushed() { + return flushed; + }; + @Override public boolean isFluidValid(int tank, FluidStack stack) { return DestroyFluids.isMixture(stack); From 397ccc7e255f4f6b69b44230a6f0f1ebd04dd2b1 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 4 Apr 2025 14:52:14 +0200 Subject: [PATCH 50/56] =?UTF-8?q?=F0=9F=8D=B2=20Can't=20forget=20about=20B?= =?UTF-8?q?asins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added configs for burner and cooler temperatures, removed configs for heating power - Updated Basin reactions to the new heating system - Fixed Basin reactions displaying pollution particles even if no gas was generated - Fixed fireproofing recipes duplicating entire stacks of items - Fixed fireproofing recipes breaking when viewing them on a multiplayer server --- .../chemistry/legacy/LegacyMixture.java | 30 +++++++++++--- .../FlameRetardantApplicationCategory.java | 3 +- .../destroy/config/DestroyBlocksConfigs.java | 9 ++++- .../fireretardant/FireproofingHelper.java | 4 +- .../basinreaction/ReactionInBasinRecipe.java | 11 ++++-- .../core/chemistry/vat/IVatHeaterBlock.java | 39 ++++--------------- .../vat/VatControllerBlockEntity.java | 2 +- .../chemistry/vat/VatSideBlockEntity.java | 2 - .../core/pollution/PollutionHelper.java | 3 +- .../destroy/mixin/patch/ContaminantMixin.java | 28 +++++++++++++ src/main/resources/destroy.mixins.json | 1 + 11 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/petrolpark/destroy/mixin/patch/ContaminantMixin.java diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java index 7cb29c058..8f4b9010f 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/LegacyMixture.java @@ -723,18 +723,36 @@ protected void incrementReactionResults(LegacyReaction reaction, float molesPerB * @param heatingPower The power being supplied to this Basin by the {@link com.petrolpark.destroy.core.chemistry.vat.IVatHeaterBlock heater} below it. * @param outsideTemperature The {@link com.petrolpark.destroy.core.pollution.Pollution#getLocalTemperature temperature} outside the Basin. */ - public ReactionInBasinResult reactInBasin(int volume, List availableStacks, float heatingPower, float outsideTemperature) { + public ReactionInBasinResult reactInBasin(int volume, List availableStacks, float heatingTemperature, float outsideTemperature) { float volumeInLiters = (float)volume / Constants.MILLIBUCKETS_PER_LITER; int ticks = 0; + // Bottom face receives heat, other faces dissipate heat into the environment + // The bottom face is more conductive than the other faces, this is balanced in such a way that a kindled Blaze Burner + // reaches roughly 130°C and a superheated Blaze Burner reaches roughly 360°C, hot enough to boil mercury + float averageTemperature = (1.35f * heatingTemperature + 4.65f * outsideTemperature) / 6f; + ReactionContext context = new ReactionContext(availableStacks, 0f, false); dissolveItems(context, volumeInLiters); // Dissolve all Items - while (!equilibrium && ticks < 600) { // React the Mixture - float energyChange = heatingPower / TICKS_PER_SECOND; - energyChange += (outsideTemperature - temperature) * 100f / TICKS_PER_SECOND; // Fourier's Law (sort of), the Basin has a fixed conductance of 100 andthe divide by 20 is for 20 ticks per second - if (Math.abs(energyChange) > 0.0001f) { - heat(1000 * energyChange / volume); // 1000 converts getFluidAmount() in mB to Buckets + while (ticks < 600) { // React the Mixture + // Fourier's Law (sort of), the Basin has a fixed conductance and the divide by 20 is for 20 ticks per second + // The Basin is given unrealistically high conductance to help make it more reliable by ensuring that the + // contained Mixture reaches its target temperature quickly. + float temperatureDifference = averageTemperature - temperature; + float energyChange = temperatureDifference * 300000f / TICKS_PER_SECOND; + float predictedMixtureTemperatureChange = Math.abs(energyChange / (volumeInLiters * getVolumetricHeatCapacity())); + + if (predictedMixtureTemperatureChange > 0.001f) { + // Prevent temperature from exploding to infinity due to the high conductance and time step + // This is a certified Euler moment and I'm too lazy to switch over to a fancier integrator for the moment + if (predictedMixtureTemperatureChange > Math.abs(temperatureDifference)) + energyChange *= 0.99f * Math.abs(temperatureDifference) / predictedMixtureTemperatureChange; + + heat(energyChange / volumeInLiters); + } else if(equilibrium) { + break; }; + reactForTick(context, 1); ticks++; }; diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/category/FlameRetardantApplicationCategory.java b/src/main/java/com/petrolpark/destroy/compat/jei/category/FlameRetardantApplicationCategory.java index 9ace125b4..cd838111f 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/category/FlameRetardantApplicationCategory.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/category/FlameRetardantApplicationCategory.java @@ -39,7 +39,8 @@ public FlameRetardantApplicationCategory(Info i @Override public void setRecipe(IRecipeLayoutBuilder builder, FlameRetardantApplicationRecipe recipe, IFocusGroup focuses) { boolean example = focuses.getFocuses(VanillaTypes.ITEM_STACK, RecipeIngredientRole.INPUT).findAny().isEmpty(); - List items = example ? exampleItems : focuses.getItemStackFocuses(RecipeIngredientRole.INPUT).map(IFocus::getTypedValue).map(ITypedIngredient::getIngredient).toList(); + List items = example ? exampleItems : focuses.getItemStackFocuses(RecipeIngredientRole.INPUT).map(IFocus::getTypedValue).map(ITypedIngredient::getIngredient) + .map(i -> i.copyWithCount(1)).toList(); builder.addSlot(RecipeIngredientRole.INPUT, 27, 51) .setBackground(getRenderedSlot(), -1, -1) diff --git a/src/main/java/com/petrolpark/destroy/config/DestroyBlocksConfigs.java b/src/main/java/com/petrolpark/destroy/config/DestroyBlocksConfigs.java index 87737c335..291f5be5c 100644 --- a/src/main/java/com/petrolpark/destroy/config/DestroyBlocksConfigs.java +++ b/src/main/java/com/petrolpark/destroy/config/DestroyBlocksConfigs.java @@ -52,9 +52,14 @@ public class DestroyBlocksConfigs extends DestroyConfigBase { public final ConfigGroup vat = group(0, "vat", "Vat"); public final ConfigBool vatExplodesAtHighPressure = b(true, "vatExplodesAtHighPressure", "Whether Vats explode if the pressure exceeds the maximum of the weakest block."); public final ConfigInt simulationLevel = i(10, "simulationLevel", "How many times per tick reactions and thermodynamics are simulated.", "Increasing this may cause lag. Decreasing it can cause flickering in Vats."); - public final ConfigFloat blazeBurnerHeatingPower = f(15000000f, -Float.MAX_VALUE, Float.MAX_VALUE, "blazeBurnerHeatingPower", "The power supplied by kindled Blaze Burners to Vats and Basins"); + + /*public final ConfigFloat blazeBurnerHeatingPower = f(15000000f, -Float.MAX_VALUE, Float.MAX_VALUE, "blazeBurnerHeatingPower", "The power supplied by kindled Blaze Burners to Vats and Basins"); public final ConfigFloat blazeBurnerSuperHeatingPower = f(50000000f, -Float.MAX_VALUE, Float.MAX_VALUE, "blazeBurnerSuperHeatingPower", "The power supplied by superheating Blaze Burners to Vats and Basins"); - public final ConfigFloat coolerHeatingPower = f(-30000000f, -Float.MAX_VALUE, Float.MAX_VALUE, "coolerHeatingPower", "The power supplied by cooling Refrigerstraytors to Vats and Basins"); + public final ConfigFloat coolerHeatingPower = f(-30000000f, -Float.MAX_VALUE, Float.MAX_VALUE, "coolerHeatingPower", "The power supplied by cooling Refrigerstraytors to Vats and Basins");*/ + + public final ConfigFloat blazeBurnerHeatingTemperature = f(500f, -Float.MAX_VALUE, Float.MAX_VALUE, "blazeBurnerHeatingTemperature", "The difference in temperature between kindled Blaze Burners and the environment."); + public final ConfigFloat blazeBurnerSuperHeatingTemperature = f(1500f, -Float.MAX_VALUE, Float.MAX_VALUE, "blazeBurnerSuperHeatingTemperature", "The difference in temperature between superheating Blaze Burners and the environment"); + public final ConfigFloat coolerHeatingTemperature = f(-500f, -Float.MAX_VALUE, Float.MAX_VALUE, "coolerHeatingTemperature", "The difference in temperature between cooling Refrigerstraytors and the environment"); @Override public String getName() { diff --git a/src/main/java/com/petrolpark/destroy/content/product/fireretardant/FireproofingHelper.java b/src/main/java/com/petrolpark/destroy/content/product/fireretardant/FireproofingHelper.java index 025dbed52..3907321a7 100644 --- a/src/main/java/com/petrolpark/destroy/content/product/fireretardant/FireproofingHelper.java +++ b/src/main/java/com/petrolpark/destroy/content/product/fireretardant/FireproofingHelper.java @@ -53,8 +53,8 @@ public static ItemStack fillItem(Level world, int requiredAmount, ItemStack stac .map(SingleFluidRecipe.class::cast) .filter(r -> r.getRequiredFluid().test(availableFluid)) .map(r -> { - availableFluid.shrink(100); - ItemStack result = stack.copy(); + availableFluid.shrink(requiredAmount); + ItemStack result = stack.copyWithCount(1); stack.shrink(1); apply(world, result); return result; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java b/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java index ccbe7e2dd..1e635a6a8 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java @@ -59,8 +59,8 @@ public static ReactionInBasinRecipe create(Collection availableFluid Level level = basin.getLevel(); BlockPos pos = basin.getBlockPos(); - float heatingPower = IVatHeaterBlock.getHeatingPower(level, pos.below(), Direction.UP); float outsideTemperature = Pollution.getLocalTemperature(level, pos); + float heatingTemperature = outsideTemperature + IVatHeaterBlock.getTemperatureDifference(level, pos.below(), Direction.UP); ExtendedBasinBehaviour behaviour = basin.getBehaviour(ExtendedBasinBehaviour.TYPE); boolean shouldUpdateBasin = false; @@ -101,7 +101,7 @@ public static ReactionInBasinRecipe create(Collection availableFluid tryReact: if (canReact) { // TODO modify temp according to Heat Level LegacyMixture mixture = LegacyMixture.mix(mixtures); - ReactionInBasinResult result = mixture.reactInBasin(totalAmount, availableItemsCopy, heatingPower, outsideTemperature); // Mutably react the Mixture and change the Item Stacks + ReactionInBasinResult result = mixture.reactInBasin(totalAmount, availableItemsCopy, heatingTemperature, outsideTemperature); // Mutably react the Mixture and change the Item Stacks // If equilibrium was not disturbed, don't do anything else if (result.ticks() == 0) { @@ -109,7 +109,7 @@ public static ReactionInBasinRecipe create(Collection availableFluid break tryReact; }; - Phases phases = mixture.separatePhases(result.amount()); + Phases phases = mixture.separatePhases(totalAmount); // Add the resultant Mixture to the results for this Recipe FluidStack outputMixtureStack = MixtureFluid.of((int)Math.round(phases.liquidVolume()), phases.liquidMixture()); @@ -145,7 +145,10 @@ public static ReactionInBasinRecipe create(Collection availableFluid gatherReactionResults(result.reactionResults(), reactionResults, builder); // Gather all behaviour.setReactionResults(reactionResults); // Schedule the Reaction Results to occur once the Mixing has finished - behaviour.evaporatedFluid = MixtureFluid.of((int)Math.round(phases.gasVolume()), phases.gasMixture()); + if(phases.gasMixture().getTotalConcentration() > 0f) + behaviour.evaporatedFluid = MixtureFluid.of((int)Math.round(phases.gasVolume()), phases.gasMixture()); + else + behaviour.evaporatedFluid = FluidStack.EMPTY; shouldUpdateBasin = true; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java index 99644b1bd..9a6a46379 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java @@ -13,41 +13,16 @@ * Interface for Blocks which can heat or cool a {@link Vat}. */ public interface IVatHeaterBlock { - + /** - * Get the power (in watts) the given Block State supplies or withdraws from a {@link Vat}. + * Get the difference in temperature (in kelvin) between the given Block State and its environment. * @param level * @param blockState * @param blockPos * @param face The face of the Block State touching the Vat * @return Positive value for heaters, negative value for coolers */ - float getHeatingPower(Level level, BlockState blockState, BlockPos blockPos, Direction face); - - public static float getHeatingPower(Level level, BlockPos blockPos, Direction face) { - BlockState state = level.getBlockState(blockPos); - - if (state.isAir()) return 0f; - - // IVatHeaters - if (state.getBlock() instanceof IVatHeaterBlock heater) { - return heater.getHeatingPower(level, state, blockPos, face); - }; - - // Blaze Burners, Coolers, etc. - if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && face == Direction.UP) { - HeatLevel heatLevel = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); - if (heatLevel == HeatLevel.KINDLED) { - return DestroyAllConfigs.SERVER.blocks.blazeBurnerHeatingPower.getF(); - } else if (heatLevel == HeatLevel.SEETHING) { - return DestroyAllConfigs.SERVER.blocks.blazeBurnerSuperHeatingPower.getF(); - } else if ("FROSTING".equals(heatLevel.name())) { - return DestroyAllConfigs.SERVER.blocks.coolerHeatingPower.getF(); - }; - }; - - return 0f; - }; + float getTemperatureDifference(Level level, BlockState blockState, BlockPos blockPos, Direction face); static float getTemperatureDifference(Level level, BlockPos blockPos, Direction face) { BlockState state = level.getBlockState(blockPos); @@ -56,18 +31,18 @@ static float getTemperatureDifference(Level level, BlockPos blockPos, Direction // IVatHeaters if (state.getBlock() instanceof IVatHeaterBlock heater) { - return heater.getHeatingPower(level, state, blockPos, face); + return heater.getTemperatureDifference(level, state, blockPos, face); }; // Blaze Burners, Coolers, etc. if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && face == Direction.UP) { HeatLevel heatLevel = state.getValue(BlazeBurnerBlock.HEAT_LEVEL); if (heatLevel == HeatLevel.KINDLED) { - return 500f; + return DestroyAllConfigs.SERVER.blocks.blazeBurnerHeatingTemperature.getF(); } else if (heatLevel == HeatLevel.SEETHING) { - return 1500f; + return DestroyAllConfigs.SERVER.blocks.blazeBurnerSuperHeatingTemperature.getF(); } else if ("FROSTING".equals(heatLevel.name())) { - return -500f; + return DestroyAllConfigs.SERVER.blocks.coolerHeatingTemperature.getF(); }; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 484ff1c21..0b28470d4 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -240,7 +240,7 @@ public void tick() { if (temperatureDifference > 0.001f || predictedMixtureTemperatureChange > 0.001f) { if (predictedMixtureTemperatureChange > temperatureDifference) - energyChangeInternal *= 0.99f * Math.abs(vatTemperature - cachedMixture.getTemperature()) / predictedMixtureTemperatureChange; + energyChangeInternal *= 0.99f * temperatureDifference / predictedMixtureTemperatureChange; cachedMixture.heat(energyChangeInternal / fluidAmount); cachedMixture.disturbEquilibrium(); diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java index 9a7d8f36d..0a91fee19 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java @@ -232,7 +232,6 @@ protected void read(CompoundTag tag, boolean clientPacket) { }; controllerPosition = NbtUtils.readBlockPos(tag.getCompound("ControllerPosition")).offset(getBlockPos()); displayType = DisplayType.values()[tag.getInt("DisplayType")]; - oldPower = tag.getFloat("OldHeatingPower"); oldUV = tag.getFloat("OldUVPower"); if (tag.contains("InitializationTicks", Tag.TAG_INT)) initializationTicks = tag.getInt("InitializationTicks"); else initializationTicks = 0; if (clientPacket) { @@ -256,7 +255,6 @@ protected void write(CompoundTag tag, boolean clientPacket) { if (direction != null) tag.putInt("Side", direction.ordinal()); if (controllerPosition != null) tag.put("ControllerPosition", NbtUtils.writeBlockPos(controllerPosition.subtract(getBlockPos()))); tag.putInt("DisplayType", displayType.ordinal()); - tag.putFloat("OldHeatingPower", oldPower); tag.putFloat("OldUVPower", oldUV); if (initializationTicks > 0) tag.putInt("InitializationTicks", initializationTicks); if (clientPacket) { diff --git a/src/main/java/com/petrolpark/destroy/core/pollution/PollutionHelper.java b/src/main/java/com/petrolpark/destroy/core/pollution/PollutionHelper.java index e92996fd8..0dfca2efe 100644 --- a/src/main/java/com/petrolpark/destroy/core/pollution/PollutionHelper.java +++ b/src/main/java/com/petrolpark/destroy/core/pollution/PollutionHelper.java @@ -151,7 +151,8 @@ public static void pollute(Level level, BlockPos blockPos, float multiplier, int List nearbyEntities = level.getEntities(null, new AABB(blockPos).inflate(2)).stream().filter(e -> e instanceof LivingEntity).map(e -> (LivingEntity)e).toList(); for (FluidStack fluidStack : List.of(fluidStacks)) { pollute(level, blockPos, multiplier, fluidStack); - if (particleWeight == 1 || level.getRandom().nextInt(particleWeight) == 0); DestroyMessages.sendToAllClients(new EvaporatingFluidS2CPacket(blockPos, fluidStack)); + if (particleWeight == 1 || level.getRandom().nextInt(particleWeight) == 0) + DestroyMessages.sendToAllClients(new EvaporatingFluidS2CPacket(blockPos, fluidStack)); for (LivingEntity entity : nearbyEntities) { ChemistryHazardHelper.damage(level, entity, fluidStack, true); }; diff --git a/src/main/java/com/petrolpark/destroy/mixin/patch/ContaminantMixin.java b/src/main/java/com/petrolpark/destroy/mixin/patch/ContaminantMixin.java new file mode 100644 index 000000000..15b9ce9ac --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/patch/ContaminantMixin.java @@ -0,0 +1,28 @@ +package com.petrolpark.destroy.mixin.patch; + +import com.petrolpark.PetrolparkRegistries; +import com.petrolpark.contamination.Contaminant; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Contaminant.class) +public class ContaminantMixin { + @Shadow + protected ResourceLocation rl; + + /** + * @author _Kilburn + * @reason Temporarily patching this here so I don't have to maintain a separate fork of the Library. It's not pretty but it'll have to do for now. + */ + @Overwrite(remap=false) + public ResourceLocation getLocation() { + if (this.rl == null) { + this.rl = PetrolparkRegistries.getDataRegistry(PetrolparkRegistries.Keys.CONTAMINANT).getKey((Contaminant)(Object)this); + } + + return this.rl; + } + +} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 1edfb5c59..9eafd7bf3 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -27,6 +27,7 @@ "compat.jei.MixingCategoryMixin", "compat.jei.PackingCategoryMixin", "compat.tfmg.AdvancedDistillationCategoryMixin", + "patch.ContaminantMixin", "AbstractContainerMenuMixin", "AirCurrentMixin", "BasinBlockEntityMixin", From 97ee61a387373619d931c31edf61f77ffc830a91 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 4 Apr 2025 18:43:24 +0200 Subject: [PATCH 51/56] =?UTF-8?q?=F0=9F=92=B5=20Caching=20out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Average external temperature is now cached and recalculated whenever a block adjacent to the Vat changes - Fixed decaying items not initializing their internal timer when precipitated from a Vat - Renamed some functions because I forgot "relative" is a word that exists --- .../PrecipitateReactionResult.java | 5 ++- .../basinreaction/ReactionInBasinRecipe.java | 2 +- .../core/chemistry/vat/IVatHeaterBlock.java | 8 ++-- .../vat/VatControllerBlockEntity.java | 42 ++++++++++--------- .../chemistry/vat/VatSideBlockEntity.java | 2 +- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/chemistry/legacy/reactionresult/PrecipitateReactionResult.java b/src/main/java/com/petrolpark/destroy/chemistry/legacy/reactionresult/PrecipitateReactionResult.java index fb2bdf8c6..61dd79305 100644 --- a/src/main/java/com/petrolpark/destroy/chemistry/legacy/reactionresult/PrecipitateReactionResult.java +++ b/src/main/java/com/petrolpark/destroy/chemistry/legacy/reactionresult/PrecipitateReactionResult.java @@ -8,6 +8,7 @@ import com.petrolpark.destroy.chemistry.legacy.LegacyReaction; import com.petrolpark.destroy.chemistry.legacy.ReactionResult; import com.petrolpark.destroy.core.chemistry.vat.VatControllerBlockEntity; +import com.petrolpark.item.decay.IDecayingItem; import com.simibubi.create.content.processing.basin.BasinBlockEntity; import net.minecraft.world.item.ItemStack; @@ -38,7 +39,9 @@ public void onBasinReaction(Level level, BasinBlockEntity basin) { @Override public void onVatReaction(Level level, VatControllerBlockEntity vatController) { - ItemHandlerHelper.insertItemStacked(vatController.inventory, precipitate.get(), false); + ItemStack result = precipitate.get(); + IDecayingItem.startDecay(result); + ItemHandlerHelper.insertItemStacked(vatController.inventory, result, false); }; @Override diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java b/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java index 1e635a6a8..ea4778986 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/basinreaction/ReactionInBasinRecipe.java @@ -60,7 +60,7 @@ public static ReactionInBasinRecipe create(Collection availableFluid Level level = basin.getLevel(); BlockPos pos = basin.getBlockPos(); float outsideTemperature = Pollution.getLocalTemperature(level, pos); - float heatingTemperature = outsideTemperature + IVatHeaterBlock.getTemperatureDifference(level, pos.below(), Direction.UP); + float heatingTemperature = outsideTemperature + IVatHeaterBlock.getRelativeTemperature(level, pos.below(), Direction.UP); ExtendedBasinBehaviour behaviour = basin.getBehaviour(ExtendedBasinBehaviour.TYPE); boolean shouldUpdateBasin = false; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java index 9a6a46379..7bed5fa26 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/IVatHeaterBlock.java @@ -15,23 +15,23 @@ public interface IVatHeaterBlock { /** - * Get the difference in temperature (in kelvin) between the given Block State and its environment. + * Get the temperature (in kelvin) of the given Block State relative to ambient temperature. * @param level * @param blockState * @param blockPos * @param face The face of the Block State touching the Vat * @return Positive value for heaters, negative value for coolers */ - float getTemperatureDifference(Level level, BlockState blockState, BlockPos blockPos, Direction face); + float getRelativeTemperature(Level level, BlockState blockState, BlockPos blockPos, Direction face); - static float getTemperatureDifference(Level level, BlockPos blockPos, Direction face) { + static float getRelativeTemperature(Level level, BlockPos blockPos, Direction face) { BlockState state = level.getBlockState(blockPos); if (state.isAir()) return 0f; // IVatHeaters if (state.getBlock() instanceof IVatHeaterBlock heater) { - return heater.getTemperatureDifference(level, state, blockPos, face); + return heater.getRelativeTemperature(level, state, blockPos, face); }; // Blaze Burners, Coolers, etc. diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 0b28470d4..4176f45c8 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -56,7 +56,6 @@ import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -93,8 +92,16 @@ public class VatControllerBlockEntity extends SmartBlockEntity implements IHaveL */ protected float UVPower; + /** + * The temperature of the walls of the Vat (not its contents) + */ protected float vatTemperature; + /** + * The average temperature outside the Vat relative to ambient temperature + */ + protected float averageOutsideRelativeTemperature; + /* * As the client side doesn't have access to the cached Mixture, store the pressure, temperature, and whether it is boiling or at equilibrium */ @@ -195,12 +202,7 @@ public void tick() { // Heating float ambientTemperature = Pollution.getLocalTemperature(getLevel(), getBlockPos()); - float averageTemperature = (float)vat.getSideBlockPositions().stream().mapToDouble(pos -> - getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()) - .map(vatSide -> IVatHeaterBlock.getTemperatureDifference(getLevel(), pos.relative(vatSide.direction), vatSide.direction.getOpposite()) - * VatMaterial.getMaterial(vatSide.getMaterial()).get().thermalConductivity()) - .orElse(0f)).sum(); - averageTemperature = Math.max(0f, ambientTemperature + averageTemperature / vat.getConductance()); + float averageTemperature = Math.max(0f, ambientTemperature + averageOutsideRelativeTemperature); int vatSideVolume = vat.getSideBlockPositions().size(); @@ -329,7 +331,7 @@ protected void read(CompoundTag tag, boolean clientPacket) { super.read(tag, clientPacket); UVPower = tag.getFloat("UVPower"); - + averageOutsideRelativeTemperature = tag.getFloat("AverageOutsideRelativeTemperature"); vatTemperature = tag.getFloat("VatTemperature"); // Vat @@ -362,7 +364,7 @@ protected void write(CompoundTag tag, boolean clientPacket) { super.write(tag, clientPacket); tag.putFloat("UVPower", UVPower); - + tag.putFloat("AverageOutsideRelativeTemperature", averageOutsideRelativeTemperature); tag.putFloat("VatTemperature", vatTemperature); // Vat @@ -502,18 +504,19 @@ public boolean tryMakeVat() { return true; }; - public void recomputeVatPower() { + public void recomputeHeatSources() { if (!hasLevel() || getLevel().isClientSide() || !vat.isPresent()) return; - vat.get().getSideBlockPositions().forEach(pos -> { - BlockState state = getLevel().getBlockState(pos); - if (state.is(DestroyBlocks.VAT_CONTROLLER.get())) return; + float newRelativeTemperature = (float)vat.get().getSideBlockPositions().stream().mapToDouble(pos -> + getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()) + .map(vatSide -> IVatHeaterBlock.getRelativeTemperature(getLevel(), pos.relative(vatSide.direction), vatSide.direction.getOpposite()) + * VatMaterial.getMaterial(vatSide.getMaterial()).get().thermalConductivity()) + .orElse(0f)).sum() / vat.get().getConductance(); - getLevel().getBlockEntity(pos, DestroyBlockEntityTypes.VAT_SIDE.get()).ifPresent(vatSide -> { - BlockPos adjacentPos = pos.relative(vatSide.direction); - vatSide.setPowerFromAdjacentBlock(adjacentPos); - }); - }); + if(newRelativeTemperature != averageOutsideRelativeTemperature) { + averageOutsideRelativeTemperature = newRelativeTemperature; + sendData(); + } } private void finalizeVatConstruction() { @@ -560,6 +563,7 @@ public void deleteVat(BlockPos posDestroyed) { }; }); UVPower = 0f; + averageOutsideRelativeTemperature = 0f; cachedMixture = new LegacyMixture(); vat = Optional.empty(); @@ -680,7 +684,7 @@ public float getPercent() { @SuppressWarnings("null") public float getTemperature() { if (getLevel().isClientSide()) return temperature.getChaseTarget(); // It thinks getLevel() might be null (it's not) - if (getVatOptional().isEmpty() || cachedMixture == null) return Pollution.getLocalTemperature(getLevel(), getBlockPos()); + if (getVatOptional().isEmpty() || cachedMixture == null) return vatTemperature; return cachedMixture.getTemperature(); }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java index 0a91fee19..efc9d4c55 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatSideBlockEntity.java @@ -340,7 +340,7 @@ public void setPowerFromAdjacentBlock(BlockPos heaterOrLampPos) { vatController.changeUVPower(newUVPower - oldUV); oldUV = newUVPower; }; - + vatController.recomputeHeatSources(); sendData(); }; From 3026befe4972a92b5e9bd9ec04804199c3baaa02 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Fri, 4 Apr 2025 18:55:47 +0200 Subject: [PATCH 52/56] =?UTF-8?q?=E2=9C=92=EF=B8=8F=20Speelchecking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed a few spelling errors - Reverted previous change to vat temperature localization - the temperature of the actual Vat is now referred to as "Wall Temperature" --- .../resources/assets/destroy/lang/en_us.json | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/resources/assets/destroy/lang/en_us.json b/src/main/resources/assets/destroy/lang/en_us.json index fa4b43a69..14fd34f47 100644 --- a/src/main/resources/assets/destroy/lang/en_us.json +++ b/src/main/resources/assets/destroy/lang/en_us.json @@ -139,9 +139,9 @@ "block.destroy.beaker.tooltip": "BEAKER", "block.destroy.beaker.tooltip.summary": "A vessel which can store and transport _medium_ amount of Mixture. Can be _placed_ and easily picked up.", "block.destroy.beaker.tooltip.condition1": "When Right-Clicked", - "block.destroy.beaker.tooltip.behaviour1": "_Empties_ the Beaker into the targeted recepticle.", + "block.destroy.beaker.tooltip.behaviour1": "_Empties_ the Beaker into the targeted receptacle.", "block.destroy.beaker.tooltip.condition2": "When Left-Clicked", - "block.destroy.beaker.tooltip.behaviour2": "_Fills_ the Beaker from the targeted recepticle.", + "block.destroy.beaker.tooltip.behaviour2": "_Fills_ the Beaker from the targeted receptacle.", "block.destroy.blacklight": "Blacklight", "block.destroy.blowpipe": "Blowpipe", "block.destroy.borosilicate_glass": "Borosilicate Glass", @@ -205,9 +205,9 @@ "block.destroy.measuring_cylinder.filled": "Measuring Cylinder of %1$s", "block.destroy.measuring_cylinder.tooltip.summary": "A vessel which can transfer _exact_ amounts of Mixture.", "block.destroy.measuring_cylinder.tooltip.condition1": "When Right-Clicked and Held", - "block.destroy.measuring_cylinder.tooltip.behaviour1": "_Empties_ a specific amount into the targeted recepticle.", + "block.destroy.measuring_cylinder.tooltip.behaviour1": "_Empties_ a specific amount into the targeted receptacle.", "block.destroy.measuring_cylinder.tooltip.condition2": "When Left-Clicked and Held", - "block.destroy.measuring_cylinder.tooltip.behaviour2": "_Fills_ a specific amount from the targeted recepticle.", + "block.destroy.measuring_cylinder.tooltip.behaviour2": "_Fills_ a specific amount from the targeted receptacle.", "block.destroy.mechanical_sieve": "Mechanical Sieve", "block.destroy.mercury_periodic_table_block": "Mercury Element Block", "block.destroy.molten_borosilicate_glass": "Molten Borosilicate Glass", @@ -249,9 +249,9 @@ "block.destroy.round_bottomed_flask.filled": "Round-Bottomed Flask of %1$s", "block.destroy.round_bottomed_flask.tooltip.summary": "A vessel which can store and transport _medium_ amount of Mixture. Can be _placed_ and easily picked up.", "block.destroy.round_bottomed_flask.tooltip.condition1": "When Right-Clicked", - "block.destroy.round_bottomed_flask.tooltip.behaviour1": "_Empties_ the Flask into the targeted recepticle.", + "block.destroy.round_bottomed_flask.tooltip.behaviour1": "_Empties_ the Flask into the targeted receptacle.", "block.destroy.round_bottomed_flask.tooltip.condition2": "When Left-Clicked", - "block.destroy.round_bottomed_flask.tooltip.behaviour2": "_Fills_ the Flask from the targeted recepticle.", + "block.destroy.round_bottomed_flask.tooltip.behaviour2": "_Fills_ the Flask from the targeted receptacle.", "block.destroy.sandcastle": "Sandcastle", "block.destroy.siphon": "Redstone Siphon", "block.destroy.siphon.drain_amount": "Amount to Drain", @@ -623,8 +623,8 @@ "destroy.display_source.colorimeter.species_name.dont_include": "No Molecule name", "destroy.display_source.mixture.temperature_unit": "Temperature Unit", "destroy.display_source.mixture.temperature_unit.kelvin": "Kelvins", - "destroy.display_source.mixture.temperature_unit.celcius": "Degrees Celcius", - "destroy.display_source.mixture.temperature_unit.farenheit": "Degrees Farenheit", + "destroy.display_source.mixture.temperature_unit.celcius": "Degrees Celsius", + "destroy.display_source.mixture.temperature_unit.farenheit": "Degrees Fahrenheit", "destroy.display_source.mixture.molecule_name_type": "Molecule Names", "destroy.display_source.mixture.molecule_name_type.iupac": "IUPAC Names", "destroy.display_source.mixture.molecule_name_type.common": "Common Names", @@ -1465,8 +1465,8 @@ "destroy.tooltip.vat.pressure.header": "Vat Pressure:", "destroy.tooltip.vat.pressure.max": "Maximum: %1$skPa (%2$s)", "destroy.tooltip.vat.power": "Power Supplied: %1$skW", - "destroy.tooltip.vat.temperature": "Mixture Temperature: %1$s", - "destroy.tooltip.vat.temperature.outer": "Vat Temperature: %1$s", + "destroy.tooltip.vat.temperature": "Vat Temperature: %1$s", + "destroy.tooltip.vat.temperature.outer": "Wall Temperature: %1$s", "destroy.tooltip.vat.reacting.header": "Reacting", "destroy.tooltip.vat.reacting": "The Mixture in this Vat is constantly changing. It will be difficult to extract it.", "destroy.tooltip.vat_material.conductivity": "Conductivity:", @@ -1892,9 +1892,9 @@ "item.destroy.test_tube.tooltip": "TEST_TUBE", "item.destroy.test_tube.tooltip.summary": "A vessel that can contain a _small_ amount of _liquid_ Mixture.", "item.destroy.test_tube.tooltip.condition1": "When Right-Clicked", - "item.destroy.test_tube.tooltip.behaviour1": "_Empties_ the Test Tube into the targeted recepticle.", + "item.destroy.test_tube.tooltip.behaviour1": "_Empties_ the Test Tube into the targeted receptacle.", "item.destroy.test_tube.tooltip.condition2": "When Left-Clicked", - "item.destroy.test_tube.tooltip.behaviour2": "_Fills_ the Test Tube from the targeted recepticle.", + "item.destroy.test_tube.tooltip.behaviour2": "_Fills_ the Test Tube from the targeted receptacle.", "item.destroy.thermite_brownie": "Thermite Brownie", "item.destroy.thermite_brownie.tooltip": "THERMITE_BROWNIE", "item.destroy.thermite_brownie.tooltip.summary": "This brownie is even spicier than normal. Your _Blaze Burners_ love them.", From e3e9736274c8b61653e1513cda54a361ba389227 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 5 Apr 2025 16:10:45 +0200 Subject: [PATCH 53/56] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Version=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Increased version number - Added config toggle for 3D molecule rendering in JEI - Fixed Vats starting out at absolute zero when loaded from a previous version --- gradle.properties | 2 +- .../compat/jei/MoleculeJEIIngredient.java | 52 ++++++++++--------- .../config/DestroyClientChemistryConfigs.java | 2 + .../vat/VatControllerBlockEntity.java | 5 +- .../mixin/MountedFluidStorageMixin.java | 5 +- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/gradle.properties b/gradle.properties index e2dc43119..65510a691 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G org.gradle.daemon = false # Destroy info -mod_version = 0.1.1-snapshot-i+0 +mod_version = 0.1.1-snapshot-i+1 minecraft_version = 1.20.1 forge_version = 47.3.7 diff --git a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java index be737b2ad..e7db104b4 100644 --- a/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java +++ b/src/main/java/com/petrolpark/destroy/compat/jei/MoleculeJEIIngredient.java @@ -118,37 +118,41 @@ public ItemStack getCheatItemStack(LegacySpecies ingredient) { @Override public void render(GuiGraphics graphics, LegacySpecies ingredient) { - MoleculeRenderer renderer = ingredient.getRenderer(); - - MultiBufferSource.BufferSource buffer = graphics.bufferSource(); - PoseStack poseStack = graphics.pose(); - poseStack.pushPose(); - renderer.renderItem(0, 0, 16, 16, poseStack, buffer); - buffer.endBatch(); - - if(ingredient.getCharge() != 0) - { - String s = ingredient.getCharge() > 0 ? "+" : "-"; - int col = 0xFFFFFF; - - if(Math.abs(ingredient.getCharge()) > 1) - s = Math.abs(ingredient.getCharge()) + s; + if(DestroyAllConfigs.CLIENT.chemistry.fancyMoleculeRendering.get()) { + MoleculeRenderer renderer = ingredient.getRenderer(); + MultiBufferSource.BufferSource buffer = graphics.bufferSource(); + PoseStack poseStack = graphics.pose(); poseStack.pushPose(); - poseStack.translate(0, 0, 100); - Font fontRenderer = Minecraft.getInstance().font; - graphics.drawString(fontRenderer, FormattedCharSequence.forward(s, FONT), -1, -1, col, true); + renderer.renderItem(0, 0, 16, 16, poseStack, buffer); + buffer.endBatch(); + + if (ingredient.getCharge() != 0) + { + String s = ingredient.getCharge() > 0 ? "+" : "-"; + int col = 0xFFFFFF; + + if (Math.abs(ingredient.getCharge()) > 1) + s = Math.abs(ingredient.getCharge()) + s; + + poseStack.pushPose(); + poseStack.translate(0, 0, 100); + Font fontRenderer = Minecraft.getInstance().font; + graphics.drawString(fontRenderer, FormattedCharSequence.forward(s, FONT), -1, -1, col, true); + poseStack.popPose(); + } poseStack.popPose(); - } - - poseStack.popPose(); - - //graphics.renderItem(MoleculeDisplayItem.with(ingredient), 0, 0); // TODO check positioning + } else { + graphics.renderItem(MoleculeDisplayItem.with(ingredient), 0, 0); // TODO check positioning + }; }; @Override public void renderBatch(GuiGraphics graphics, List> elements) { - batchRenderer.renderBatch(graphics, elements); + if(DestroyAllConfigs.CLIENT.chemistry.fancyMoleculeRendering.get()) + batchRenderer.renderBatch(graphics, elements); + else + IIngredientRenderer.super.renderBatch(graphics, elements); } @Override diff --git a/src/main/java/com/petrolpark/destroy/config/DestroyClientChemistryConfigs.java b/src/main/java/com/petrolpark/destroy/config/DestroyClientChemistryConfigs.java index 2f1c3f872..9146fb4a1 100644 --- a/src/main/java/com/petrolpark/destroy/config/DestroyClientChemistryConfigs.java +++ b/src/main/java/com/petrolpark/destroy/config/DestroyClientChemistryConfigs.java @@ -6,6 +6,7 @@ public class DestroyClientChemistryConfigs extends DestroyConfigBase { public final ConfigBool iupacNames = b(false, "iupacNames", Comments.iupacNames, Comments.reloadRequired); public final ConfigEnum temperatureUnit = e(TemperatureUnit.DEGREES_CELCIUS, "temperatureUnit", Comments.temperatureUnit, Comments.reloadRequired); + public final ConfigBool fancyMoleculeRendering = b(true, "fancyMoleculeRendering", Comments.fancyMoleculeRendering); public final ConfigBool nerdMode = b(false, "nerdMode", Comments.nerdMode); @Override @@ -17,6 +18,7 @@ private static class Comments { static String iupacNames = "Show IUPAC systematic names rather than common names", temperatureUnit = "Units of temperature to display by default", + fancyMoleculeRendering = "Display molecules as their 3D representation in JEI", nerdMode = "Display additional technical details in some tooltips", reloadRequired = "[Reload may be required to take full effect]"; }; diff --git a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java index 4176f45c8..8fb3ca9eb 100644 --- a/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java +++ b/src/main/java/com/petrolpark/destroy/core/chemistry/vat/VatControllerBlockEntity.java @@ -332,7 +332,10 @@ protected void read(CompoundTag tag, boolean clientPacket) { UVPower = tag.getFloat("UVPower"); averageOutsideRelativeTemperature = tag.getFloat("AverageOutsideRelativeTemperature"); - vatTemperature = tag.getFloat("VatTemperature"); + if(tag.contains("VatTemperature")) + vatTemperature = tag.getFloat("VatTemperature"); + else + vatTemperature = getLevel() == null ? 289f : Pollution.getLocalTemperature(getLevel(), getBlockPos()); // Initialize default temperature if we're loading from a previous version // Vat if (tag.contains("Vat", Tag.TAG_COMPOUND)) { diff --git a/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java index 17e50790b..54f62c1e9 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/MountedFluidStorageMixin.java @@ -3,17 +3,14 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.simibubi.create.content.contraptions.MountedFluidStorage; -import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; import com.simibubi.create.foundation.fluid.SmartFluidTank; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.fluids.FluidStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.petrolpark.destroy.core.fluid.GeniusFluidTankBehaviour.GeniusFluidTank; @@ -43,7 +40,7 @@ private void createGeniusMountedTank(BlockEntity be, CallbackInfoReturnable original) { + private static SmartFluidTank deserializeGeniusMountedTank(int capacity, Consumer updateCallback, Operation original) { return new GeniusFluidTank(capacity, updateCallback); } From fd7572f0931fc559d99e13f72a0a9e8465a50281 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Sat, 5 Apr 2025 16:16:13 +0200 Subject: [PATCH 54/56] =?UTF-8?q?=F0=9F=92=A5=20Mixed=20opinion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mixed explosives with high instability now explode instantly when triggered by a nearby explosion - Other mixed explosives now get a reduced fuse time when triggered by a nearby explosion - Fixed mixed explosives not having their properties set when dispensed by a Dispenser - Fixed mixed explosives dropping themselves as an item when triggered by a nearby explosion --- .../com/petrolpark/destroy/DestroyBlocks.java | 2 +- .../core/explosion/SmartExplosion.java | 2 +- .../mixedexplosive/MixedExplosiveBlock.java | 133 ++++++++++++++++-- 3 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/petrolpark/destroy/DestroyBlocks.java b/src/main/java/com/petrolpark/destroy/DestroyBlocks.java index 4e87c445f..963d8bf41 100644 --- a/src/main/java/com/petrolpark/destroy/DestroyBlocks.java +++ b/src/main/java/com/petrolpark/destroy/DestroyBlocks.java @@ -203,7 +203,7 @@ public class DestroyBlocks { .properties(p -> p .mapColor(MapColor.SNOW) ).item(MixedExplosiveBlockItem::new) - .onRegister(registerPrimeableBombDispenserBehaviour()) + .onRegister(item -> DispenserBlock.registerBehavior(item, ((MixedExplosiveBlock)item.getBlock()).new CustomExplosiveMixDispenseBehaviour())) .build() .register(); diff --git a/src/main/java/com/petrolpark/destroy/core/explosion/SmartExplosion.java b/src/main/java/com/petrolpark/destroy/core/explosion/SmartExplosion.java index 7591f0fa1..2c20e6e9e 100644 --- a/src/main/java/com/petrolpark/destroy/core/explosion/SmartExplosion.java +++ b/src/main/java/com/petrolpark/destroy/core/explosion/SmartExplosion.java @@ -262,7 +262,7 @@ public ExplosionResult getExplosionResult() { */ public void explodeBlock(BlockPos pos) { BlockState state = level.getBlockState(pos); - if (level instanceof ServerLevel serverLevel) { + if (level instanceof ServerLevel serverLevel && state.canDropFromExplosion(level, pos, this)) { BlockEntity blockEntity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; LootParams.Builder builder = new LootParams.Builder(serverLevel) .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) diff --git a/src/main/java/com/petrolpark/destroy/core/explosion/mixedexplosive/MixedExplosiveBlock.java b/src/main/java/com/petrolpark/destroy/core/explosion/mixedexplosive/MixedExplosiveBlock.java index 4450669cf..23845f49c 100644 --- a/src/main/java/com/petrolpark/destroy/core/explosion/mixedexplosive/MixedExplosiveBlock.java +++ b/src/main/java/com/petrolpark/destroy/core/explosion/mixedexplosive/MixedExplosiveBlock.java @@ -7,13 +7,19 @@ import com.petrolpark.destroy.DestroyBlocks; import com.petrolpark.destroy.DestroyEntityTypes; import com.petrolpark.destroy.core.explosion.PrimeableBombBlock; +import com.petrolpark.destroy.core.explosion.PrimedBombEntity; import com.petrolpark.destroy.core.explosion.SmartExplosion; import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockSource; import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.OptionalDispenseItemBehavior; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -22,11 +28,15 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DispenserBlock; 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.level.gameevent.GameEvent; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.BlockHitResult; @@ -34,6 +44,8 @@ import net.minecraft.world.phys.Vec3; import net.minecraftforge.network.NetworkHooks; +import javax.annotation.Nullable; + public class MixedExplosiveBlock extends PrimeableBombBlock implements IBE { public MixedExplosiveBlock(Properties properties) { @@ -42,18 +54,19 @@ public MixedExplosiveBlock(Properties properties) { @Override public void onCaughtFire(BlockState state, Level level, BlockPos pos, Direction face, LivingEntity igniter) { - withBlockEntityDo(level, pos, be -> { - MixedExplosiveInventory inv = be.getExplosiveInventory(); - if (inv.isEmpty()) return; - ExplosiveProperties properties = inv.getExplosiveProperties(); - if (properties.fulfils(ExplosiveProperties.NO_FUSE)) { - level.removeBlock(pos, false); - if (level instanceof ServerLevel serverLevel) SmartExplosion.explode(serverLevel, CustomExplosiveMixExplosion.create(level, inv, igniter, Vec3.atCenterOf(pos))); - } else if (properties.fulfils(ExplosiveProperties.CAN_EXPLODE)) { - super.onCaughtFire(state, level, pos, face, igniter); - level.removeBlock(pos, false); - }; - }); + new MixedExplosivePrimer(level, pos, state) + .setIgniter(igniter) + .setIgnitionFace(face) + .prime(); + }; + + @Override + public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) { + new MixedExplosivePrimer(level, pos, state) + .setIgniter(explosion.getIndirectSourceEntity()) + .setTriggeredByExplosion(true) + .prime(); + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); }; @Override @@ -73,6 +86,11 @@ public boolean isRandomlyTicking(BlockState state) { return true; }; + @Override + public boolean canDropFromExplosion(BlockState state, BlockGetter level, BlockPos pos, Explosion explosion) { + return level.getBlockEntity(pos) instanceof MixedExplosiveBlockEntity be && be.getExplosiveInventory().getExplosiveProperties().fulfils(ExplosiveProperties.CAN_EXPLODE); + }; + @Override public void randomTick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { withBlockEntityDo(pLevel, pPos, be -> { @@ -139,6 +157,85 @@ public BlockEntityType getBlockEntityType() return DestroyBlockEntityTypes.CUSTOM_EXPLOSIVE_MIX.get(); }; + public static class MixedExplosivePrimer { + private Level level; + private BlockPos pos; + private BlockState state; + private int color = 0xFFFFFF; + private MixedExplosiveInventory inv = null; + private Component customName = null; + private boolean triggeredByExplosion = false; + private LivingEntity igniter = null; + private Direction face = null; + + public MixedExplosivePrimer(Level level, BlockPos pos, BlockState state) { + this.level = level; + this.pos = pos; + this.state = state; + + if(level.getBlockEntity(pos) instanceof MixedExplosiveBlockEntity be) { + color = be.getColor(); + inv = be.getExplosiveInventory(); + customName = be.getCustomName(); + }; + }; + + public MixedExplosivePrimer(Level level, BlockPos pos, ItemStack itemStack) { + this.level = level; + this.pos = pos; + this.state = null; + + if(itemStack.getItem() instanceof MixedExplosiveBlockItem item) { + color = item.getColor(itemStack); + inv = item.getExplosiveInventory(itemStack); + customName = itemStack.getDisplayName(); + }; + }; + + public MixedExplosivePrimer setTriggeredByExplosion(boolean b) { + triggeredByExplosion = b; + return this; + }; + + public MixedExplosivePrimer setIgniter(LivingEntity e) { + igniter = e; + return this; + }; + + public MixedExplosivePrimer setIgnitionFace(Direction d) { + face = d; + return this; + }; + + public boolean prime() { + if (inv == null || inv.isEmpty()) return false; + + ExplosiveProperties properties = inv.getExplosiveProperties(); + if (properties.fulfils(ExplosiveProperties.CAN_EXPLODE)) { + if(level instanceof ServerLevel) { + MixedExplosiveEntity entity = new MixedExplosiveEntity(level, pos, state, igniter, color, inv); + entity.setCustomName(customName); + level.addFreshEntity(entity); + if(properties.fulfils(ExplosiveProperties.NO_FUSE)) { + entity.setFuse(1); + } else if(triggeredByExplosion) { + int i = entity.getFuse(); + entity.setFuse((short)(level.random.nextInt(i / 4) + i / 8)); + } else { + level.playSound(null, entity.getX(), entity.getY(), entity.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0f, 1.0f); + } + level.gameEvent(igniter, GameEvent.PRIME_FUSE, pos); + }; + if(state != null) + level.removeBlock(pos, false); + return true; + }; + + return false; + }; + }; + + // This actually doesn't get used anymore public static class CustomExplosiveMixEntityFactory implements PrimedBombEntityFactory { @Override @@ -151,5 +248,17 @@ public MixedExplosiveEntity create(Level level, BlockPos pos, BlockState state, }; }; + + public class CustomExplosiveMixDispenseBehaviour extends OptionalDispenseItemBehavior { + + @Override + protected ItemStack execute(BlockSource blockSource, ItemStack stack) { + Level level = blockSource.getLevel(); + BlockPos pos = blockSource.getPos().relative(blockSource.getBlockState().getValue(DispenserBlock.FACING)); + if(new MixedExplosivePrimer(level, pos, stack).prime()) + stack.shrink(1); + return stack; + }; + }; }; From 2e97490df7fec7f477fe4f9cef72857a31346a28 Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Mon, 7 Apr 2025 05:27:41 +0200 Subject: [PATCH 55/56] =?UTF-8?q?=F0=9F=8C=88=20Mixin=20it=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed Mixtures seen through transparent pipes not updating when the color of their source changes - Multiple Mixtures can now travel down the same pipe network and will visually mix when seen through transparent pipes - Supplementaries compat: Faucets now properly transfer Mixtures and voiding Mixtures using a sponge now pollutes the world accordingly --- build.gradle | 4 ++ gradle/gradle-daemon-jvm.properties | 2 - .../mixin/FluidTransportBehaviourMixin.java | 71 +++++++++++++++++++ .../destroy/mixin/PipeConnectionMixin.java | 30 ++++++-- .../SoftFluidStackImplMixin.java | 22 ++++++ .../SpongeInteractionMixin.java | 29 ++++++++ src/main/resources/destroy.mixins.json | 3 + 7 files changed, 152 insertions(+), 9 deletions(-) delete mode 100644 gradle/gradle-daemon-jvm.properties create mode 100644 src/main/java/com/petrolpark/destroy/mixin/FluidTransportBehaviourMixin.java create mode 100644 src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SoftFluidStackImplMixin.java create mode 100644 src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java diff --git a/build.gradle b/build.gradle index 820759178..189afad7f 100644 --- a/build.gradle +++ b/build.gradle @@ -233,6 +233,10 @@ dependencies { implementation fg.deobf("com.rbasamoyai:ritchiesprojectilelib:1.0.0-369e88d+1.20.1-forge") implementation fg.deobf("com.rbasamoyai:createbigcannons:${cbc_version}") + // Supplementaries + implementation fg.deobf("maven.modrinth:moonlight:forge_1.20-2.13.71") + implementation fg.deobf("maven.modrinth:supplementaries:1.20-3.1.18") + // Embeddium implementation fg.deobf("maven.modrinth:embeddium:${embeddium_version}+mc${minecraft_version}") diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties deleted file mode 100644 index 858feb7e3..000000000 --- a/gradle/gradle-daemon-jvm.properties +++ /dev/null @@ -1,2 +0,0 @@ -#This file is generated by updateDaemonJvm -toolchainVersion=17 diff --git a/src/main/java/com/petrolpark/destroy/mixin/FluidTransportBehaviourMixin.java b/src/main/java/com/petrolpark/destroy/mixin/FluidTransportBehaviourMixin.java new file mode 100644 index 000000000..5fafbd27a --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/FluidTransportBehaviourMixin.java @@ -0,0 +1,71 @@ +package com.petrolpark.destroy.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.petrolpark.destroy.DestroyFluids; +import com.petrolpark.destroy.chemistry.legacy.LegacyMixture; +import com.petrolpark.destroy.chemistry.minecraft.MixtureFluid; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import net.minecraftforge.fluids.FluidStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.util.Map; + +@Mixin(FluidTransportBehaviour.class) +public class FluidTransportBehaviourMixin { + private ThreadLocal accumulatedAvailableFluid = new ThreadLocal<>(); + + @WrapOperation( + method = "tick()V", + at = @At( + value = "INVOKE", + target = "Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z", + remap = false + ), + remap = false + ) + private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operation original) { + if(original.call(fluid, other)) + return true; + else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { + return true; + } + + return false; + } + + @ModifyVariable( + method = "tick()V", + name = "availableFlow", + at = @At("STORE"), + remap = false + ) + private FluidStack accumulateAvailableFluidStack(FluidStack providedFluid) { + if(providedFluid.isEmpty()) { + // If providedFluid is empty, we just initialized availableFlow + accumulatedAvailableFluid.set(FluidStack.EMPTY); + } else if(DestroyFluids.isMixture(providedFluid)) { + if(accumulatedAvailableFluid.get().isEmpty()) { + // First Mixture input, remember it and carry on as normal + accumulatedAvailableFluid.set(providedFluid); + return providedFluid; + } else { + // If this pipe segments has multiple Mixture inputs, mix them together + // This is purely visual for the sake of displaying flowing liquids in transparent pipes + LegacyMixture existingMixture = LegacyMixture.readNBT(accumulatedAvailableFluid.get().getOrCreateTag().getCompound("Mixture")); + LegacyMixture addedMixture = LegacyMixture.readNBT(providedFluid.getOrCreateTag().getCompound("Mixture")); + int existingAmount = accumulatedAvailableFluid.get().getAmount(); + int addedAmount = providedFluid.getAmount(); + LegacyMixture newMixture = LegacyMixture.mix(Map.of(existingMixture, existingAmount/1000d, addedMixture, addedAmount/1000d)); + + accumulatedAvailableFluid.set(MixtureFluid.of(existingAmount + addedAmount, newMixture)); + return accumulatedAvailableFluid.get(); + } + } + + // Not a Mixture input, carry on as normal + return providedFluid; + } +} diff --git a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java index 463417007..5ebde69aa 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/PipeConnectionMixin.java @@ -28,15 +28,30 @@ @Mixin(PipeConnection.class) public class PipeConnectionMixin { - private Optional retainedNetwork = Optional.empty(); + private ThreadLocal> retainedNetwork = new ThreadLocal<>(); + private ThreadLocal shouldUpdateData = new ThreadLocal<>(); @Inject( - method="Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", + method= "manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", at=@At("HEAD"), remap=false ) - private void onStartManageFlows(Level world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate, CallbackInfoReturnable cir) { - retainedNetwork = ((PipeConnectionAccessor)this).getNetwork(); + private void manageFlows_onStart(Level world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate, CallbackInfoReturnable cir) { + retainedNetwork.set(((PipeConnectionAccessor)this).getNetwork()); + shouldUpdateData.set(false); + } + + @Inject( + method= "manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", + at=@At("RETURN"), + cancellable = true, + remap=false + ) + private void manageFlows_onReturn(Level world, BlockPos pos, FluidStack internalFluid, Predicate extractionPredicate, CallbackInfoReturnable cir) { + // Returning true from PipeConnection.manageFlows causes its data to be sent from the server to the client. + // We want that to happen whenever the Mixture carried by this connection changes. + if(shouldUpdateData.get()) + cir.setReturnValue(true); } /** @@ -45,7 +60,7 @@ private void onStartManageFlows(Level world, BlockPos pos, FluidStack internalFl * these change a lot. We don't want to try restarting the flow every tick. */ @WrapOperation( - method="Lcom/simibubi/create/content/fluids/PipeConnection;manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", + method= "manageFlows(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraftforge/fluids/FluidStack;Ljava/util/function/Predicate;)Z", at=@At( value="INVOKE", target="Lnet/minecraftforge/fluids/FluidStack;isFluidEqual(Lnet/minecraftforge/fluids/FluidStack;)Z" @@ -57,8 +72,9 @@ private boolean considerMixturesEqual(FluidStack fluid, FluidStack other, Operat return true; else if(DestroyFluids.isMixture(fluid) && DestroyFluids.isMixture(other)) { ((PipeConnectionAccessor)this).getFlow().get().fluid = fluid; - if(retainedNetwork.isPresent()) - ((FluidNetworkAccessor)retainedNetwork.get()).setFluid(fluid); + if(retainedNetwork.get().isPresent()) + ((FluidNetworkAccessor)retainedNetwork.get().get()).setFluid(fluid); + shouldUpdateData.set(true); return true; } diff --git a/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SoftFluidStackImplMixin.java b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SoftFluidStackImplMixin.java new file mode 100644 index 000000000..a7c1e9c1c --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SoftFluidStackImplMixin.java @@ -0,0 +1,22 @@ +package com.petrolpark.destroy.mixin.compat.supplementaries; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.mehvahdjukaar.moonlight.api.fluids.SoftFluidStack; +import net.mehvahdjukaar.moonlight.api.fluids.forge.SoftFluidStackImpl; +import net.minecraftforge.fluids.FluidStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(SoftFluidStackImpl.class) +public class SoftFluidStackImplMixin { + @WrapMethod( + method = "Lnet/mehvahdjukaar/moonlight/api/fluids/forge/SoftFluidStackImpl;toForgeFluid(Lnet/mehvahdjukaar/moonlight/api/fluids/SoftFluidStack;)Lnet/minecraftforge/fluids/FluidStack;", + remap = false + ) + private static FluidStack toForgeFluid(SoftFluidStack softFluid, Operation original) { + FluidStack stack = original.call(softFluid); + if(softFluid.hasTag() && softFluid.getTag().contains("Mixture")) + stack.getOrCreateTag().put("Mixture", softFluid.getTag().getCompound("Mixture")); + return stack; + } +} diff --git a/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java new file mode 100644 index 000000000..2a0bad736 --- /dev/null +++ b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java @@ -0,0 +1,29 @@ +package com.petrolpark.destroy.mixin.compat.supplementaries; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.petrolpark.destroy.core.pollution.PollutionHelper; +import net.mehvahdjukaar.moonlight.api.fluids.forge.SoftFluidStackImpl; +import net.mehvahdjukaar.supplementaries.common.block.faucet.FluidOffer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(targets = "net/mehvahdjukaar/supplementaries/common/block/faucet/SpongeInteraction") +public class SpongeInteractionMixin { + @WrapMethod( + method = "fill", + remap = false + ) + public Integer fill(Level level, BlockPos pos, BlockState target, FluidOffer offer, Operation original) { + Integer result = original.call(level, pos, target, offer); + if(result != null && result.intValue() > 0) { + FluidStack fluidStack = SoftFluidStackImpl.toForgeFluid(offer.fluid().copyWithCount(result.intValue())); + PollutionHelper.pollute(level, pos, 1.f, 1, fluidStack); + }; + return target.getBlock() == Blocks.SPONGE ? offer.minAmount() : null; + } +} diff --git a/src/main/resources/destroy.mixins.json b/src/main/resources/destroy.mixins.json index 9eafd7bf3..e4c685d71 100644 --- a/src/main/resources/destroy.mixins.json +++ b/src/main/resources/destroy.mixins.json @@ -27,6 +27,8 @@ "compat.jei.MixingCategoryMixin", "compat.jei.PackingCategoryMixin", "compat.tfmg.AdvancedDistillationCategoryMixin", + "compat.supplementaries.SoftFluidStackImplMixin", + "compat.supplementaries.SpongeInteractionMixin", "patch.ContaminantMixin", "AbstractContainerMenuMixin", "AirCurrentMixin", @@ -41,6 +43,7 @@ "FluidNetworkMixin", "FluidPropagatorMixin", "FluidTankBlockEntityMixin", + "FluidTransportBehaviourMixin", "GenericItemFillingMixin", "GhostItemMenuMixin", "HeatConditionMixin", From 81be6d96fac96ee32d18b8be8d9524047295578d Mon Sep 17 00:00:00 2001 From: UnderscoreKilburn Date: Wed, 9 Apr 2025 14:08:44 +0200 Subject: [PATCH 56/56] =?UTF-8?q?=F0=9F=A7=BD=20Minor=20Supplementaries=20?= =?UTF-8?q?compat=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compat/supplementaries/SpongeInteractionMixin.java | 3 ++- .../tags/blocks/faucet_connection_blacklist.json | 8 ++++++++ .../{ => tags/items}/blackboard_white.json | 0 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/data/supplementaries/tags/blocks/faucet_connection_blacklist.json rename src/main/resources/data/supplementaries/{ => tags/items}/blackboard_white.json (100%) diff --git a/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java index 2a0bad736..214ac3c36 100644 --- a/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java +++ b/src/main/java/com/petrolpark/destroy/mixin/compat/supplementaries/SpongeInteractionMixin.java @@ -21,9 +21,10 @@ public class SpongeInteractionMixin { public Integer fill(Level level, BlockPos pos, BlockState target, FluidOffer offer, Operation original) { Integer result = original.call(level, pos, target, offer); if(result != null && result.intValue() > 0) { + // Voiding fluids by pouring them onto a sponge releases them into the atmosphere FluidStack fluidStack = SoftFluidStackImpl.toForgeFluid(offer.fluid().copyWithCount(result.intValue())); PollutionHelper.pollute(level, pos, 1.f, 1, fluidStack); }; - return target.getBlock() == Blocks.SPONGE ? offer.minAmount() : null; + return result; } } diff --git a/src/main/resources/data/supplementaries/tags/blocks/faucet_connection_blacklist.json b/src/main/resources/data/supplementaries/tags/blocks/faucet_connection_blacklist.json new file mode 100644 index 000000000..650310eb6 --- /dev/null +++ b/src/main/resources/data/supplementaries/tags/blocks/faucet_connection_blacklist.json @@ -0,0 +1,8 @@ +{ + "replace": false, + "values": [ + {"id":"destroy:beaker","required":false}, + {"id":"destroy:measuring_cylinder","required":false}, + {"id":"destroy:round_bottomed_flask","required":false} + ] +} \ No newline at end of file diff --git a/src/main/resources/data/supplementaries/blackboard_white.json b/src/main/resources/data/supplementaries/tags/items/blackboard_white.json similarity index 100% rename from src/main/resources/data/supplementaries/blackboard_white.json rename to src/main/resources/data/supplementaries/tags/items/blackboard_white.json