hollow-cube/prevent-block-placement-outside-world (#42)

* Prevent block place above 320

(cherry picked from commit d226c3994a)

* Move position of check

(cherry picked from commit ff7c4c108f)

* Add unit test

(cherry picked from commit 68500bf0d0)

* Add min y check

(cherry picked from commit 0ce77673a9)

---------

Co-authored-by: nucker <nuckermail@gmail.com>
(cherry picked from commit 8da8a70342)
This commit is contained in:
Matt Worzala 2023-08-05 13:10:37 -04:00
parent ccb7a81dc9
commit c657be553f
4 changed files with 43 additions and 15 deletions

View File

@ -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<Section> 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();

View File

@ -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();

View File

@ -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());

View File

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