From 1a19a43b8110e83a78b292417ad80d03f56d861d Mon Sep 17 00:00:00 2001 From: TheRealWormbo Date: Mon, 1 Apr 2024 18:50:41 +0200 Subject: [PATCH] Fix Warp+Force lens behavior when hitting force relays (fixes #4046) --- Fabric/src/main/resources/fabric.mod.json | 3 +- .../botania/common/item/lens/ForceLens.java | 11 ++ .../java/vazkii/botania/test/TestingUtil.java | 12 ++ .../botania/test/item/lens/WarpForceTest.java | 106 ++++++++++++++++++ .../lens/force_warp_relay_interaction.snbt | 23 ++++ 5 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 Xplat/src/main/java/vazkii/botania/test/item/lens/WarpForceTest.java create mode 100644 Xplat/src/main/resources/data/botania/gametest/structures/item/lens/force_warp_relay_interaction.snbt diff --git a/Fabric/src/main/resources/fabric.mod.json b/Fabric/src/main/resources/fabric.mod.json index 75b5bd7fa6..76540d8c2c 100644 --- a/Fabric/src/main/resources/fabric.mod.json +++ b/Fabric/src/main/resources/fabric.mod.json @@ -54,7 +54,8 @@ "vazkii.botania.test.item.SpectatorScanTest", "vazkii.botania.test.item.lens.BoreLensTest", "vazkii.botania.test.item.lens.EntropicWarpLensTest", - "vazkii.botania.test.item.lens.PaintslingerLensTest" + "vazkii.botania.test.item.lens.PaintslingerLensTest", + "vazkii.botania.test.item.lens.WarpForceTest" ], "fabric-datagen": [ "vazkii.botania.fabric.data.FabricDatagenInitializer" diff --git a/Xplat/src/main/java/vazkii/botania/common/item/lens/ForceLens.java b/Xplat/src/main/java/vazkii/botania/common/item/lens/ForceLens.java index f842fba21e..3836033a26 100644 --- a/Xplat/src/main/java/vazkii/botania/common/item/lens/ForceLens.java +++ b/Xplat/src/main/java/vazkii/botania/common/item/lens/ForceLens.java @@ -14,11 +14,14 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import vazkii.botania.api.internal.ManaBurst; +import vazkii.botania.common.block.BotaniaBlocks; import vazkii.botania.common.helper.ForcePushHelper; +import vazkii.botania.common.item.BotaniaItems; import vazkii.botania.mixin.PistonBaseBlockAccessor; public class ForceLens extends Lens { @@ -30,6 +33,14 @@ public boolean collideBurst(ManaBurst burst, HitResult pos, boolean isManaBlock, && !burst.isFake() && !isManaBlock) { BlockHitResult rtr = (BlockHitResult) pos; + BlockState state = entity.level().getBlockState(rtr.getBlockPos()); + ItemStack sourceLens = burst.getSourceLens(); + boolean isWarp = sourceLens.is(BotaniaItems.lensWarp); + if (isWarp && state.is(BotaniaBlocks.pistonRelay)) { + // warp+force should not move the force relay + return false; + } + // mana burst could have been warped here, so don't assume that any block is unmovable moveBlocks(entity.level(), rtr.getBlockPos().relative(rtr.getDirection()), rtr.getDirection().getOpposite(), ManaBurst.NO_SOURCE); } diff --git a/Xplat/src/main/java/vazkii/botania/test/TestingUtil.java b/Xplat/src/main/java/vazkii/botania/test/TestingUtil.java index 4f506ca8d9..3f6390e75a 100644 --- a/Xplat/src/main/java/vazkii/botania/test/TestingUtil.java +++ b/Xplat/src/main/java/vazkii/botania/test/TestingUtil.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable; +import vazkii.botania.common.block.ForceRelayBlock; import vazkii.botania.common.item.BotaniaItems; import java.util.Objects; @@ -118,4 +119,15 @@ public static void bindWithWandOfTheForest(GameTestHelper helper, BlockPos first player.setPos(Vec3.atCenterOf(second)); useItemOn(helper, player, InteractionHand.MAIN_HAND, second); } + + public static void bindForceRelayTarget(GameTestHelper helper, BlockPos relayPos, BlockPos targetPos) { + var data = ForceRelayBlock.WorldData.get(helper.getLevel()); + data.mapping.put(helper.absolutePos(relayPos), helper.absolutePos(targetPos)); + } + + @Nullable + public static BlockPos getBoundForceRelayTarget(GameTestHelper helper, BlockPos relayPos) { + var data = ForceRelayBlock.WorldData.get(helper.getLevel()); + return data.mapping.get(helper.absolutePos(relayPos)); + } } diff --git a/Xplat/src/main/java/vazkii/botania/test/item/lens/WarpForceTest.java b/Xplat/src/main/java/vazkii/botania/test/item/lens/WarpForceTest.java new file mode 100644 index 0000000000..c89bb76dbe --- /dev/null +++ b/Xplat/src/main/java/vazkii/botania/test/item/lens/WarpForceTest.java @@ -0,0 +1,106 @@ +package vazkii.botania.test.item.lens; + +import net.minecraft.core.BlockPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.ButtonBlock; +import net.minecraft.world.level.block.state.BlockState; + +import vazkii.botania.common.block.BotaniaBlocks; +import vazkii.botania.common.block.block_entity.BotaniaBlockEntities; +import vazkii.botania.common.item.BotaniaItems; +import vazkii.botania.common.item.lens.LensItem; +import vazkii.botania.test.TestingUtil; + +public class WarpForceTest { + private static final String TEMPLATE = "botania:item/lens/force_warp_relay_interaction"; + + private static final BlockPos SPREADER_POS = new BlockPos(1, 2, 1); + private static final BlockPos SPREADER_TARGET_POS = new BlockPos(6, 2, 1); + private static final BlockPos BUTTON_POS = new BlockPos(1, 2, 3); + private static final BlockPos RELAY_POS = new BlockPos(3, 2, 1); + private static final BlockPos BOUND_POS = new BlockPos(3, 2, 3); + + @GameTest(template = TEMPLATE, timeoutTicks = 50) + public void testWarpForceLens(GameTestHelper helper) { + setUpLensesAndBindings(helper, BotaniaItems.lensWarp, BotaniaItems.lensPiston); + + helper.startSequence() + .thenExecute(() -> helper.pressButton(BUTTON_POS)) + .thenWaitUntil(() -> helper.assertBlockProperty(BUTTON_POS, ButtonBlock.POWERED, false)) + .thenExecute(() -> { + helper.assertBlock(RELAY_POS, BotaniaBlocks.pistonRelay::equals, () -> "Force relay moved"); + helper.assertBlockState(BOUND_POS, BlockState::isAir, () -> "Bound block did not move"); + helper.assertBlock(BOUND_POS.east(), Blocks.POLISHED_ANDESITE::equals, + () -> "Bound block did not move to expected position"); + TestingUtil.assertEquals(TestingUtil.getBoundForceRelayTarget(helper, RELAY_POS), helper.absolutePos(BOUND_POS), + () -> "Relay binding has changed"); + }) + // second shot to confirm binding still works + .thenExecute(() -> helper.setBlock(BOUND_POS, Blocks.POLISHED_DIORITE)) + .thenExecute(() -> helper.pressButton(BUTTON_POS)) + .thenWaitUntil(() -> helper.assertBlockProperty(BUTTON_POS, ButtonBlock.POWERED, false)) + .thenExecute(() -> { + helper.assertBlockState(RELAY_POS, blockState -> blockState.is(BotaniaBlocks.pistonRelay), + () -> "Force relay moved after second burst"); + helper.assertBlockState(BOUND_POS, BlockState::isAir, () -> "Bound block did not move"); + helper.assertBlock(BOUND_POS.east(), Blocks.POLISHED_DIORITE::equals, + () -> "New block did not move to expected position after second burst"); + helper.assertBlock(BOUND_POS.east(2), Blocks.POLISHED_ANDESITE::equals, + () -> "Original block did not move to expected position after second burst"); + TestingUtil.assertEquals(TestingUtil.getBoundForceRelayTarget(helper, RELAY_POS), helper.absolutePos(BOUND_POS), + () -> "Relay binding has changed after second burst"); + }) + .thenSucceed(); + } + + // TODO: Regression test for https://github.com/VazkiiMods/Botania/issues/4593 + @GameTest(template = TEMPLATE, timeoutTicks = 50, required = false) + public void testForceWarpLens(GameTestHelper helper) { + setUpLensesAndBindings(helper, BotaniaItems.lensPiston, BotaniaItems.lensWarp); + + helper.startSequence() + .thenExecute(() -> helper.pressButton(BUTTON_POS)) + .thenWaitUntil(() -> helper.assertBlockProperty(BUTTON_POS, ButtonBlock.POWERED, false)) + .thenExecute(() -> { + helper.assertBlockState(RELAY_POS, BlockState::isAir, () -> "Force relay did not move"); + helper.assertBlock(RELAY_POS.east(), BotaniaBlocks.pistonRelay::equals, + () -> "Force relay did not move to expected position"); + helper.assertBlockState(BOUND_POS, BlockState::isAir, () -> "Bound block did not move"); + helper.assertBlock(BOUND_POS.east(), Blocks.POLISHED_ANDESITE::equals, + () -> "Bound block did not move to expected position"); + TestingUtil.assertEquals(TestingUtil.getBoundForceRelayTarget(helper, RELAY_POS.east()), BOUND_POS.east(), + () -> "Relay binding was not updated"); + }) + // second shot to confirm binding still works + .thenExecute(() -> helper.setBlock(BOUND_POS, Blocks.POLISHED_DIORITE)) + .thenExecute(() -> helper.pressButton(BUTTON_POS)) + .thenWaitUntil(() -> helper.assertBlockProperty(BUTTON_POS, ButtonBlock.POWERED, false)) + .thenExecute(() -> { + helper.assertBlock(BOUND_POS, Blocks.POLISHED_DIORITE::equals, () -> "New block at original bound position moved"); + helper.assertBlockState(RELAY_POS.east(), BlockState::isAir, () -> "Force relay did not move after second burst"); + helper.assertBlock(RELAY_POS.east(2), BotaniaBlocks.pistonRelay::equals, + () -> "Force relay did not move to expected position after second burst"); + helper.assertBlockState(BOUND_POS.east(), BlockState::isAir, () -> "Bound block did not move a second time"); + helper.assertBlock(BOUND_POS.east(2), Blocks.POLISHED_ANDESITE::equals, + () -> "Bound block did not move to expected position after second burst"); + TestingUtil.assertEquals(TestingUtil.getBoundForceRelayTarget(helper, RELAY_POS.east(2)), BOUND_POS.east(2), + () -> "Relay binding was not updated after second burst"); + }) + .thenSucceed(); + } + + private static void setUpLensesAndBindings(GameTestHelper helper, Item firstLensType, Item secondLensType) { + final var warpLensStack = new ItemStack(firstLensType); + final var forceLensStack = new ItemStack(secondLensType); + final var compositeLens = ((LensItem) warpLensStack.getItem()).setCompositeLens(warpLensStack, forceLensStack); + final var spreaderEntity = TestingUtil.assertBlockEntity(helper, SPREADER_POS, BotaniaBlockEntities.SPREADER); + spreaderEntity.getItemHandler().setItem(0, compositeLens); + + TestingUtil.bindWithWandOfTheForest(helper, SPREADER_POS, SPREADER_TARGET_POS); + TestingUtil.bindForceRelayTarget(helper, RELAY_POS, BOUND_POS); + } +} diff --git a/Xplat/src/main/resources/data/botania/gametest/structures/item/lens/force_warp_relay_interaction.snbt b/Xplat/src/main/resources/data/botania/gametest/structures/item/lens/force_warp_relay_interaction.snbt new file mode 100644 index 0000000000..08206b6e51 --- /dev/null +++ b/Xplat/src/main/resources/data/botania/gametest/structures/item/lens/force_warp_relay_interaction.snbt @@ -0,0 +1,23 @@ +{ + DataVersion: 3465, + size: [7, 3, 5], + data: [ + {pos: [1, 1, 1], state: "botania:redstone_spreader{has_scaffolding:false,waterlogged:false}"}, + {pos: [1, 1, 2], state: "minecraft:polished_andesite"}, + {pos: [1, 1, 3], state: "minecraft:polished_blackstone_button{face:wall,facing:south,powered:false}"}, + {pos: [3, 1, 1], state: "botania:piston_relay"}, + {pos: [3, 1, 3], state: "minecraft:polished_andesite"}, + {pos: [6, 1, 1], state: "minecraft:obsidian"}, + {pos: [6, 1, 3], state: "minecraft:obsidian"}, + {pos: [1, 2, 1], state: "botania:creative_pool{color:none,waterlogged:false}"} + ], + entities: [], + palette: [ + "minecraft:polished_andesite", + "botania:piston_relay", + "minecraft:obsidian", + "minecraft:polished_blackstone_button{face:wall,facing:south,powered:false}", + "botania:redstone_spreader{has_scaffolding:false,waterlogged:false}", + "botania:creative_pool{color:none,waterlogged:false}" + ] +}