From 6422b9857e52071fa28ad476b5ce9dfd64b6c67d Mon Sep 17 00:00:00 2001 From: Nicole <52045376+drfiveminusmint@users.noreply.github.com> Date: Sat, 14 Sep 2024 14:56:18 -0400 Subject: [PATCH] Piston bugfix (#713) * Test potential origin of bug It could be possible that cancelling these events has some adverse effects. * Disable old fix * Disable another potential origin * debug messages for monitoring * Potentially detect more piston events * fix events * detect processing * Test potential fix * Update IWorldHandler.java * Try to catch problems in the WorldHandler * Update IWorldHandler.java * Use NMS code to fix pistons * Update IWorldHandler.java * Remove old fixes and 1.21 implementation Also removed debug messages * Missed a debug message * Fix unintentional wildcard imports --- .../async/rotation/RotationTask.java | 9 ----- .../async/translation/TranslationTask.java | 13 +++---- .../movecraft/listener/BlockListener.java | 37 +++++++++++++------ .../movecraft/compat/v1_20/IWorldHandler.java | 31 +++++++++++++++- .../movecraft/compat/v1_21/IWorldHandler.java | 31 +++++++++++++--- 5 files changed, 85 insertions(+), 36 deletions(-) diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/async/rotation/RotationTask.java b/Movecraft/src/main/java/net/countercraft/movecraft/async/rotation/RotationTask.java index 5c7711797..586aea1a0 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/async/rotation/RotationTask.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/async/rotation/RotationTask.java @@ -114,15 +114,6 @@ protected void execute() { MovecraftLocation newLocation = MathUtils.rotateVec(rotation,originalLocation.subtract(originPoint)).add(originPoint); newHitBox.add(newLocation); - //Prevent piston bug - if (originalLocation.toBukkit(getCraft().getWorld()).getBlock().getType().equals(Material.MOVING_PISTON)) { - failed = true; - failMessage = (String.format(I18nSupport.getInternationalisedString("Translation - Failed Craft is obstructed") - + " @ %d,%d,%d,%s", originalLocation.getX(), originalLocation.getY(), originalLocation.getZ(), - originalLocation.toBukkit(craft.getWorld()).getBlock().getType())); - break; - } - Material oldMaterial = originalLocation.toBukkit(w).getBlock().getType(); //prevent chests collision if (Tags.CHESTS.contains(oldMaterial) && !checkChests(oldMaterial, newLocation)) { diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/async/translation/TranslationTask.java b/Movecraft/src/main/java/net/countercraft/movecraft/async/translation/TranslationTask.java index 936da69ac..a1a9390b6 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/async/translation/TranslationTask.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/async/translation/TranslationTask.java @@ -5,7 +5,11 @@ import net.countercraft.movecraft.MovecraftLocation; import net.countercraft.movecraft.async.AsyncTask; import net.countercraft.movecraft.config.Settings; -import net.countercraft.movecraft.craft.*; +import net.countercraft.movecraft.craft.ChunkManager; +import net.countercraft.movecraft.craft.Craft; +import net.countercraft.movecraft.craft.CraftManager; +import net.countercraft.movecraft.craft.SinkingCraft; +import net.countercraft.movecraft.craft.SubCraft; import net.countercraft.movecraft.craft.type.CraftType; import net.countercraft.movecraft.events.CraftCollisionEvent; import net.countercraft.movecraft.events.CraftCollisionExplosionEvent; @@ -24,8 +28,8 @@ import net.countercraft.movecraft.util.Tags; import net.countercraft.movecraft.util.hitboxes.HitBox; import net.countercraft.movecraft.util.hitboxes.MutableHitBox; -import net.countercraft.movecraft.util.hitboxes.SolidHitBox; import net.countercraft.movecraft.util.hitboxes.SetHitBox; +import net.countercraft.movecraft.util.hitboxes.SolidHitBox; import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -166,11 +170,6 @@ protected void execute() throws InterruptedException, ExecutionException { newHitBox.add(newLocation); continue; } - //Prevent piston bug - if (oldLocation.toBukkit(world).getBlock().getType().equals(Material.MOVING_PISTON)) - fail(String.format(I18nSupport.getInternationalisedString("Translation - Failed Craft is obstructed") - + " @ %d,%d,%d,%s", oldLocation.getX(), oldLocation.getY(), oldLocation.getZ(), - oldLocation.toBukkit(craft.getWorld()).getBlock().getType())); final Material testMaterial = newLocation.toBukkit(world).getBlock().getType(); diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/listener/BlockListener.java b/Movecraft/src/main/java/net/countercraft/movecraft/listener/BlockListener.java index 0ce37d5ef..68829f398 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/listener/BlockListener.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/listener/BlockListener.java @@ -42,9 +42,11 @@ import org.bukkit.event.block.BlockFormEvent; import org.bukkit.event.block.BlockFromToEvent; import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPistonEvent; import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockRedstoneEvent; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.material.Attachable; @@ -123,7 +125,16 @@ public void onRedstoneEvent(@NotNull BlockRedstoneEvent e) { } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPistonEvent(@NotNull BlockPistonExtendEvent e) { + public void onPistonExtendEvent(@NotNull BlockPistonExtendEvent e) { + onPistonEvent(e); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPistonRetractEvent(@NotNull BlockPistonRetractEvent e) { + onPistonEvent(e); + } + + public void onPistonEvent(@NotNull BlockPistonEvent e) { Block block = e.getBlock(); Location location = block.getLocation(); MovecraftLocation loc = MathUtils.bukkit2MovecraftLoc(location); @@ -131,22 +142,24 @@ public void onPistonEvent(@NotNull BlockPistonExtendEvent e) { if (!craft.getHitBox().contains(loc)) continue; - if (!craft.isNotProcessing()) - e.setCancelled(true); // prevent pistons on cruising crafts - + if (!craft.isNotProcessing()) + e.setCancelled(true); // prevent pistons on cruising crafts + if (!(e instanceof BlockPistonExtendEvent)) + return; // merge piston extensions to craft - if (craft.getType().getBoolProperty(CraftType.MERGE_PISTON_EXTENSIONS)) + if (craft.getType().getBoolProperty(CraftType.MERGE_PISTON_EXTENSIONS)) continue; - BitmapHitBox hitBox = new BitmapHitBox(); - for (Block b : e.getBlocks()) { - Vector dir = e.getDirection().getDirection(); - hitBox.add(new MovecraftLocation(b.getX() + dir.getBlockX(), b.getY() + dir.getBlockY(), b.getZ() + dir.getBlockZ())); - } - craft.setHitBox(craft.getHitBox().union(hitBox)); + BitmapHitBox hitBox = new BitmapHitBox(); + for (Block b : ((BlockPistonExtendEvent) e).getBlocks()) { + Vector dir = e.getDirection().getDirection(); + hitBox.add(new MovecraftLocation(b.getX() + dir.getBlockX(), b.getY() + dir.getBlockY(), b.getZ() + dir.getBlockZ())); + } + craft.setHitBox(craft.getHitBox().union(hitBox)); } } + // prevent hoppers on cruising crafts @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onHopperEvent(@NotNull InventoryMoveItemEvent e) { diff --git a/v1_20/src/main/java/net/countercraft/movecraft/compat/v1_20/IWorldHandler.java b/v1_20/src/main/java/net/countercraft/movecraft/compat/v1_20/IWorldHandler.java index 74ab3bdf8..ae8d6a930 100644 --- a/v1_20/src/main/java/net/countercraft/movecraft/compat/v1_20/IWorldHandler.java +++ b/v1_20/src/main/java/net/countercraft/movecraft/compat/v1_20/IWorldHandler.java @@ -8,16 +8,23 @@ import net.countercraft.movecraft.util.MathUtils; import net.countercraft.movecraft.util.UnsafeUtils; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.level.BlockEventData; 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.DirectionalBlock; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.piston.PistonBaseBlock; +import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.ticks.LevelChunkTicks; @@ -163,10 +170,12 @@ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation disp //get the nextTick to move with the tile ScheduledTick tickHere = tickProvider.getNextTick(nativeWorld, position); - if (tickHere != null) { + while (tickHere != null) { + ScheduledTick tickToRemove = tickHere; ((LevelChunkTicks) nativeWorld.getChunkAt(position).getBlockTicks()).removeIf( - (Predicate) scheduledTick -> scheduledTick.equals(tickHere)); + (Predicate) scheduledTick -> scheduledTick.equals(tickToRemove)); ticks.add(new TickHolder(tickHere, position)); + tickHere = tickProvider.getNextTick(nativeWorld, position); } } @@ -213,6 +222,24 @@ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation disp @Nullable private BlockEntity removeBlockEntity(@NotNull Level world, @NotNull BlockPos position) { + BlockEntity testEntity = world.getChunkAt(position).getBlockEntity(position); + //Prevents moving pistons by locking up by forcing their movement to finish + if (testEntity instanceof PistonMovingBlockEntity) + { + BlockState oldState; + if (((PistonMovingBlockEntity) testEntity).isSourcePiston() && testEntity.getBlockState().getBlock() instanceof PistonBaseBlock) { + if (((PistonMovingBlockEntity) testEntity).getMovedState().is(Blocks.PISTON)) + oldState = Blocks.PISTON.defaultBlockState() + .setValue(PistonBaseBlock.FACING, ((PistonMovingBlockEntity) testEntity).getMovedState().getValue(PistonBaseBlock.FACING)); + else + oldState = Blocks.STICKY_PISTON.defaultBlockState() + .setValue(PistonBaseBlock.FACING, ((PistonMovingBlockEntity) testEntity).getMovedState().getValue(PistonBaseBlock.FACING)); + } else + oldState = ((PistonMovingBlockEntity) testEntity).getMovedState(); + ((PistonMovingBlockEntity) testEntity).finalTick(); + setBlockFast(world, position, oldState); + return world.getBlockEntity(position); + } return world.getChunkAt(position).blockEntities.remove(position); } diff --git a/v1_21/src/main/java/net/countercraft/movecraft/compat/v1_21/IWorldHandler.java b/v1_21/src/main/java/net/countercraft/movecraft/compat/v1_21/IWorldHandler.java index 3a5321ffb..d4e3cba4b 100644 --- a/v1_21/src/main/java/net/countercraft/movecraft/compat/v1_21/IWorldHandler.java +++ b/v1_21/src/main/java/net/countercraft/movecraft/compat/v1_21/IWorldHandler.java @@ -9,13 +9,13 @@ import net.countercraft.movecraft.util.UnsafeUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerLevelAccess; 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.Rotation; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.piston.PistonBaseBlock; +import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; @@ -26,13 +26,14 @@ import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.data.CraftBlockData; -import org.bukkit.craftbukkit.inventory.CraftInventoryView; -import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Field; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.function.Predicate; @SuppressWarnings("unused") @@ -208,6 +209,24 @@ public void translateCraft(@NotNull Craft craft, @NotNull MovecraftLocation disp @Nullable private BlockEntity removeBlockEntity(@NotNull Level world, @NotNull BlockPos position) { + BlockEntity testEntity = world.getChunkAt(position).getBlockEntity(position); + //Prevents moving pistons by locking up by forcing their movement to finish + if (testEntity instanceof PistonMovingBlockEntity) + { + BlockState oldState; + if (((PistonMovingBlockEntity) testEntity).isSourcePiston() && testEntity.getBlockState().getBlock() instanceof PistonBaseBlock) { + if (((PistonMovingBlockEntity) testEntity).getMovedState().is(Blocks.PISTON)) + oldState = Blocks.PISTON.defaultBlockState() + .setValue(PistonBaseBlock.FACING, ((PistonMovingBlockEntity) testEntity).getMovedState().getValue(PistonBaseBlock.FACING)); + else + oldState = Blocks.STICKY_PISTON.defaultBlockState() + .setValue(PistonBaseBlock.FACING, ((PistonMovingBlockEntity) testEntity).getMovedState().getValue(PistonBaseBlock.FACING)); + } else + oldState = ((PistonMovingBlockEntity) testEntity).getMovedState(); + ((PistonMovingBlockEntity) testEntity).finalTick(); + setBlockFast(world, position, oldState); + return world.getBlockEntity(position); + } return world.getChunkAt(position).blockEntities.remove(position); }