From 8da8a703425a45366c720ebee5e7c25180e8b14d Mon Sep 17 00:00:00 2001 From: Matt Worzala <35708499+mworzala@users.noreply.github.com> Date: Sat, 5 Aug 2023 13:10:37 -0400 Subject: [PATCH] hollow-cube/prevent-block-placement-outside-world (#42) * Prevent block place above 320 (cherry picked from commit d226c3994a804320ab2a4aa4d9bd2dee777ea6c5) * Move position of check (cherry picked from commit ff7c4c108f63eb67b756bac8f54fcdbf66579075) * Add unit test (cherry picked from commit 68500bf0d0fe331a8bdbba8c7063c7f3ecdc313d) * Add min y check (cherry picked from commit 0ce77673a96df3d102aa99ddd7c3377ce44491e7) --------- Co-authored-by: nucker --- .../server/instance/DynamicChunk.java | 10 ++++++++++ .../server/instance/InstanceContainer.java | 9 +++++++++ .../listener/BlockPlacementListener.java | 20 +++++-------------- .../server/instance/BlockPlaceTest.java | 19 ++++++++++++++++++ 4 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 src/test/java/net/minestom/server/instance/BlockPlaceTest.java diff --git a/src/main/java/net/minestom/server/instance/DynamicChunk.java b/src/main/java/net/minestom/server/instance/DynamicChunk.java index 2a6918421..91f6bdafe 100644 --- a/src/main/java/net/minestom/server/instance/DynamicChunk.java +++ b/src/main/java/net/minestom/server/instance/DynamicChunk.java @@ -23,11 +23,14 @@ import net.minestom.server.utils.ArrayUtils; import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.ObjectPool; import net.minestom.server.utils.chunk.ChunkUtils; +import net.minestom.server.utils.validate.Check; import net.minestom.server.world.biomes.Biome; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jglrxavpok.hephaistos.nbt.NBT; import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; @@ -39,6 +42,7 @@ import static net.minestom.server.utils.chunk.ChunkUtils.toSectionRelativeCoordi * WARNING: not thread-safe. */ public class DynamicChunk extends Chunk { + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicChunk.class); protected List
sections; @@ -60,7 +64,13 @@ public class DynamicChunk extends Chunk { public void setBlock(int x, int y, int z, @NotNull Block block, @Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy) { + if(y >= instance.getDimensionType().getMaxY() || y < instance.getDimensionType().getMinY()) { + LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", + instance.getDimensionType().getMinY(), instance.getDimensionType().getMaxY(), y); + return; + } assertLock(); + this.lastChange = System.currentTimeMillis(); this.chunkCache.invalidate(); diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index db5f97daf..a1bc753b4 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -33,6 +33,8 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import space.vectrix.flare.fastutil.Long2ObjectSyncMap; import java.util.*; @@ -50,6 +52,8 @@ import static net.minestom.server.utils.chunk.ChunkUtils.*; * InstanceContainer is an instance that contains chunks in contrary to SharedInstance. */ public class InstanceContainer extends Instance { + private static final Logger LOGGER = LoggerFactory.getLogger(InstanceContainer.class); + private static final AnvilLoader DEFAULT_LOADER = new AnvilLoader("world"); private static final BlockFace[] BLOCK_UPDATE_FACES = new BlockFace[]{ @@ -129,6 +133,11 @@ public class InstanceContainer extends Instance { @Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy, boolean doBlockUpdates, int updateDistance) { if (chunk.isReadOnly()) return; + if(y >= getDimensionType().getMaxY() || y < getDimensionType().getMinY()) { + LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", getDimensionType().getMinY(), getDimensionType().getMaxY(), y); + return; + } + synchronized (chunk) { // Refresh the last block change time this.lastBlockChangeTime = System.currentTimeMillis(); diff --git a/src/main/java/net/minestom/server/listener/BlockPlacementListener.java b/src/main/java/net/minestom/server/listener/BlockPlacementListener.java index a3869c6f5..ed3811e07 100644 --- a/src/main/java/net/minestom/server/listener/BlockPlacementListener.java +++ b/src/main/java/net/minestom/server/listener/BlockPlacementListener.java @@ -90,6 +90,7 @@ public class BlockPlacementListener { canPlaceBlock = usedItem.meta().canPlaceOn(interactedBlock); } + // Get the newly placed block position //todo it feels like it should be possible to have better replacement rules than this, feels pretty scuffed. Point placementPosition = blockPosition; @@ -111,6 +112,9 @@ public class BlockPlacementListener { } } + if(placementPosition.y() >= instance.getDimensionType().getMaxY() + || placementPosition.y() <= instance.getDimensionType().getMinY()) return; + if (!canPlaceBlock) { // Send a block change with the real block in the instance to keep the client in sync, // using refreshChunk results in the client not being in sync @@ -150,22 +154,8 @@ public class BlockPlacementListener { return; } - // BlockPlacementRule check - Block resultBlock = playerBlockPlaceEvent.getBlock(); -// final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(resultBlock); -// if (blockPlacementRule != null && playerBlockPlaceEvent.shouldDoBlockUpdates()) { - // Get id from block placement rule instead of the event -// resultBlock = blockPlacementRule.blockPlace(new BlockPlacementRule.PlacementState( -// instance, resultBlock, blockFace, -// placementPosition, cursorPosition, -// player.getPosition(), usedItem.meta(), player.isSneaking()) -// ); -// } -// if (resultBlock == null) { -// refresh(player, chunk); -// return; -// } // Place the block + Block resultBlock = playerBlockPlaceEvent.getBlock(); player.sendPacket(new AcknowledgeBlockChangePacket(packet.sequence())); instance.placeBlock(new BlockHandler.PlayerPlacement(resultBlock, instance, placementPosition, player, hand, blockFace, packet.cursorPositionX(), packet.cursorPositionY(), packet.cursorPositionZ()), playerBlockPlaceEvent.shouldDoBlockUpdates()); diff --git a/src/test/java/net/minestom/server/instance/BlockPlaceTest.java b/src/test/java/net/minestom/server/instance/BlockPlaceTest.java new file mode 100644 index 000000000..01dfa9848 --- /dev/null +++ b/src/test/java/net/minestom/server/instance/BlockPlaceTest.java @@ -0,0 +1,19 @@ +package net.minestom.server.instance; + +import net.minestom.server.instance.block.Block; +import net.minestom.testing.Env; +import net.minestom.testing.EnvTest; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +@EnvTest +public class BlockPlaceTest { + + @Test + void testPlacementOutOfLimit(Env env) { + Instance instance = env.createFlatInstance(); + assertDoesNotThrow(() -> instance.setBlock(0, instance.getDimensionType().getMaxY() + 1, 0, Block.STONE)); + assertDoesNotThrow(() -> instance.setBlock(0, instance.getDimensionType().getMinY() - 1, 0, Block.STONE)); + } +}