diff --git a/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/PaperweightServerLevelDelegateProxy.java b/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/PaperweightServerLevelDelegateProxy.java index 37f04531bf..c223e812c6 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/PaperweightServerLevelDelegateProxy.java +++ b/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/PaperweightServerLevelDelegateProxy.java @@ -28,7 +28,6 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.concurrency.LazyReference; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.entity.EntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; @@ -37,6 +36,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; @@ -50,6 +50,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.util.function.Predicate; public class PaperweightServerLevelDelegateProxy implements InvocationHandler { @@ -86,7 +87,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) { } private BlockState getBlockState(BlockPos blockPos) { - return adapter.adapt(this.editSession.getBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()))); + return adapter.adapt(this.editSession.getBlockWithBuffer(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()))); + } + + private boolean isStateAtPosition(BlockPos blockPos, Predicate predicate) { + return predicate.test(getBlockState(blockPos)); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { @@ -98,11 +103,7 @@ private boolean setBlock(BlockPos blockPos, BlockState blockState) { } private boolean removeBlock(BlockPos blockPos) { - try { - return editSession.setBlock(BlockVector3.at(blockPos.getX(), blockPos.getY(), blockPos.getZ()), BlockTypes.AIR.getDefaultState()); - } catch (MaxChangedBlocksException e) { - throw new RuntimeException(e); - } + return setBlock(blockPos, Blocks.AIR.defaultBlockState()); } private boolean addEntity(Entity entity) { @@ -144,6 +145,12 @@ private static void addMethodHandleToTable( lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("getBlockState", BlockPos.class)) ); + addMethodHandleToTable( + builder, + StaticRefraction.IS_STATE_AT_POSITION, + lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class)) + ); + MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class)); addMethodHandleToTable( builder, diff --git a/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/StaticRefraction.java b/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/StaticRefraction.java index c098c9efd9..56b11e71ba 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/StaticRefraction.java +++ b/worldedit-bukkit/adapters/adapter-1.21.3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_3/StaticRefraction.java @@ -37,6 +37,7 @@ public final class StaticRefraction { ); public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e"); public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_"); + public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a"); /** * {@code addFreshEntityWithPassengers(Entity entity)}. */ diff --git a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightServerLevelDelegateProxy.java b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightServerLevelDelegateProxy.java index e3dc39b3f5..3c72784170 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightServerLevelDelegateProxy.java +++ b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/PaperweightServerLevelDelegateProxy.java @@ -53,6 +53,7 @@ import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; public class PaperweightServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { @@ -99,7 +100,11 @@ private BlockEntity getBlockEntity(BlockPos blockPos) { } private BlockState getBlockState(BlockPos blockPos) { - return adapter.adapt(this.editSession.getBlock(adapt(blockPos))); + return adapter.adapt(this.editSession.getBlockWithBuffer(adapt(blockPos))); + } + + private boolean isStateAtPosition(BlockPos blockPos, Predicate predicate) { + return predicate.test(getBlockState(blockPos)); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { @@ -134,7 +139,7 @@ private void handleBlockEntity(BlockPos blockPos, BlockState blockState) { createdBlockEntities.remove(pos); } - private boolean removeBlock(BlockPos blockPos, boolean bl) { + private boolean removeBlock(BlockPos blockPos) { return setBlock(blockPos, Blocks.AIR.defaultBlockState()); } @@ -191,6 +196,12 @@ private static void addMethodHandleToTable( lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("getBlockState", BlockPos.class)) ); + addMethodHandleToTable( + builder, + StaticRefraction.IS_STATE_AT_POSITION, + lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("isStateAtPosition", BlockPos.class, Predicate.class)) + ); + MethodHandle addEntity = lookup.unreflect(PaperweightServerLevelDelegateProxy.class.getDeclaredMethod("addEntity", Entity.class)); addMethodHandleToTable( builder, diff --git a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/StaticRefraction.java b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/StaticRefraction.java index 61471ad115..9e5272571e 100644 --- a/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/StaticRefraction.java +++ b/worldedit-bukkit/adapters/adapter-1.21.4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/v1_21_4/StaticRefraction.java @@ -37,6 +37,7 @@ public final class StaticRefraction { ); public static final String NEXT_TICK_TIME = Refraction.pickName("nextTickTime", "e"); public static final String GET_BLOCK_STATE = Refraction.pickName("getBlockState", "a_"); + public static final String IS_STATE_AT_POSITION = Refraction.pickName("isStateAtPosition", "a"); /** * {@code addFreshEntityWithPassengers(Entity entity)}. */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 26c357fc20..3cf2a79a55 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -714,6 +714,30 @@ public BaseBlock getFullBlock(BlockVector3 position) { return world.getFullBlock(position); } + /** + * As with {@link #getBlock(BlockVector3)}, gets the block at the given position. + * However, this may return blocks not yet set to the world (i.e., buffered) by + * the current EditSession. + * + * @param position position of the block + * @return the block + */ + public BlockState getBlockWithBuffer(BlockVector3 position) { + return this.bypassNone.getBlock(position); + } + + /** + * As with {@link #getFullBlock(BlockVector3)}, gets the block at the given position, + * but as with {@link #getBlockWithBuffer(BlockVector3)}, this may return a block in + * the current EditSession's buffer rather than from the world. + * + * @param position position of the block + * @return the block + */ + public BaseBlock getFullBlockWithBuffer(BlockVector3 position) { + return this.bypassNone.getFullBlock(position); + } + /** * Returns the highest solid 'terrain' block. * diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java index e3bdb96309..ba3d8d9c13 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricServerLevelDelegateProxy.java @@ -41,6 +41,7 @@ import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; public class FabricServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { @@ -81,7 +82,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) { } private BlockState getBlockState(BlockPos blockPos) { - return FabricAdapter.adapt(this.editSession.getBlock(FabricAdapter.adapt(blockPos))); + return FabricAdapter.adapt(this.editSession.getBlockWithBuffer(FabricAdapter.adapt(blockPos))); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { @@ -147,6 +148,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl return getBlockState(blockPos); } } + case "isStateAtPosition", "method_16358" -> { + if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) { + @SuppressWarnings("unchecked") + Predicate predicate = (Predicate) args[1]; + return predicate.test(getBlockState(blockPos)); + } + } case "getBlockEntity", "method_8321" -> { if (args.length == 1 && args[0] instanceof BlockPos blockPos) { return getBlockEntity(blockPos); diff --git a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java index b6abff1fed..becb44030e 100644 --- a/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java +++ b/worldedit-neoforge/src/main/java/com/sk89q/worldedit/neoforge/internal/NeoForgeServerLevelDelegateProxy.java @@ -42,6 +42,7 @@ import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; public class NeoForgeServerLevelDelegateProxy implements InvocationHandler, AutoCloseable { @@ -82,7 +83,7 @@ private BlockEntity getBlockEntity(BlockPos blockPos) { } private BlockState getBlockState(BlockPos blockPos) { - return NeoForgeAdapter.adapt(this.editSession.getBlock(NeoForgeAdapter.adapt(blockPos))); + return NeoForgeAdapter.adapt(this.editSession.getBlockWithBuffer(NeoForgeAdapter.adapt(blockPos))); } private boolean setBlock(BlockPos blockPos, BlockState blockState) { @@ -150,6 +151,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl return getBlockState(blockPos); } } + case "isStateAtPosition", "m_7433_" -> { + if (args.length == 2 && args[0] instanceof BlockPos blockPos && args[1] instanceof Predicate) { + @SuppressWarnings("unchecked") + Predicate predicate = (Predicate) args[1]; + return predicate.test(getBlockState(blockPos)); + } + } case "getBlockEntity", "m_7702_" -> { if (args.length == 1 && args[0] instanceof BlockPos blockPos) { return getBlockEntity(blockPos);