Skip to content

Commit

Permalink
Piston bugfix (#713)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
drfiveminusmint authored Sep 14, 2024
1 parent 936a87a commit 6422b98
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -123,30 +125,41 @@ 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);
for (Craft craft : MathUtils.craftsNearLocFast(CraftManager.getInstance().getCrafts(), location)) {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 -> scheduledTick.equals(tickHere));
(Predicate<ScheduledTick>) scheduledTick -> scheduledTick.equals(tickToRemove));
ticks.add(new TickHolder(tickHere, position));
tickHere = tickProvider.getNextTick(nativeWorld, position);
}

}
Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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")
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 6422b98

Please sign in to comment.