From f23345041dfeafca20c2047614598374fb614245 Mon Sep 17 00:00:00 2001 From: iam4722202468 Date: Sat, 17 Feb 2024 19:39:45 -0500 Subject: [PATCH] RelativeBlockBatch update --- .../instance/batch/RelativeBlockBatch.java | 49 +++++++++++++ .../batch/RelativeBlockBatchTest.java | 69 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/test/java/net/minestom/server/instance/batch/RelativeBlockBatchTest.java diff --git a/src/main/java/net/minestom/server/instance/batch/RelativeBlockBatch.java b/src/main/java/net/minestom/server/instance/batch/RelativeBlockBatch.java index 868f49904..2c921083a 100644 --- a/src/main/java/net/minestom/server/instance/batch/RelativeBlockBatch.java +++ b/src/main/java/net/minestom/server/instance/batch/RelativeBlockBatch.java @@ -48,6 +48,55 @@ public class RelativeBlockBatch implements Batch { this.options = options; } + public RelativeBlockBatch diff(RelativeBlockBatch other) { + RelativeBlockBatch diff = new RelativeBlockBatch(); + + for (var entry : this.blockIdMap.long2ObjectEntrySet()) { + long pos = entry.getLongKey(); + final int relZ = (short) (pos & 0xFFFF) + this.offsetZ; + final int relY = (short) ((pos >> 16) & 0xFFFF) + this.offsetY; + final int relX = (short) ((pos >> 32) & 0xFFFF) + this.offsetX; + + Block otherBlock = other.getBlock(relX, relY, relZ); + Block selfBlock = entry.getValue(); + + if (otherBlock == null || !otherBlock.equals(selfBlock)) { + diff.setBlock(relX, relY, relZ, selfBlock); + } + } + + for (var entry : other.blockIdMap.long2ObjectEntrySet()) { + long pos = entry.getLongKey(); + final int relZ = (short) (pos & 0xFFFF) + other.offsetZ; + final int relY = (short) ((pos >> 16) & 0xFFFF) + other.offsetY; + final int relX = (short) ((pos >> 32) & 0xFFFF) + other.offsetX; + Block selfBlock = this.getBlock(relX, relY, relZ); + + if (selfBlock == null) { + diff.setBlock(relX, relY, relZ, Block.AIR); + } + } + + return diff; + } + + public void join(RelativeBlockBatch relativeBlockBatch) { + for (var entry : relativeBlockBatch.blockIdMap.long2ObjectEntrySet()) { + long pos = entry.getLongKey(); + final int relZ = (short) (pos & 0xFFFF) + relativeBlockBatch.offsetZ; + final int relY = (short) ((pos >> 16) & 0xFFFF) + relativeBlockBatch.offsetY; + final int relX = (short) ((pos >> 32) & 0xFFFF) + relativeBlockBatch.offsetX; + this.setBlock(relX, relY, relZ, entry.getValue()); + } + } + + public @Nullable Block getBlock(int x, int y, int z) { + long pos = Short.toUnsignedLong((short)(x - this.offsetX)); + pos = (pos << 16) | Short.toUnsignedLong((short)(y - this.offsetY)); + pos = (pos << 16) | Short.toUnsignedLong((short)(z - this.offsetZ)); + return blockIdMap.get(pos); + } + @Override public void setBlock(int x, int y, int z, @NotNull Block block) { // Save the offsets if it is the first entry diff --git a/src/test/java/net/minestom/server/instance/batch/RelativeBlockBatchTest.java b/src/test/java/net/minestom/server/instance/batch/RelativeBlockBatchTest.java new file mode 100644 index 000000000..5c7ee66b4 --- /dev/null +++ b/src/test/java/net/minestom/server/instance/batch/RelativeBlockBatchTest.java @@ -0,0 +1,69 @@ +package net.minestom.server.instance.batch; + +import net.minestom.server.instance.block.Block; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RelativeBlockBatchTest { + + @Test + public void testReadWrite() { + RelativeBlockBatch batch = new RelativeBlockBatch(); + batch.setBlock(0, 0, 0, Block.STONE); + assertEquals(Block.STONE, batch.getBlock(0, 0, 0)); + + batch.setBlock(0, 0, 0, Block.GRASS_BLOCK); + assertEquals(Block.GRASS_BLOCK, batch.getBlock(0, 0, 0)); + + batch.setBlock(0, 1, 0, Block.AIR); + assertEquals(Block.AIR, batch.getBlock(0, 1, 0)); + + batch.setBlock(0, 1, 0, Block.STONE); + assertEquals(Block.STONE, batch.getBlock(0, 1, 0)); + + batch.setBlock(1000, 1, 0, Block.GRASS_BLOCK); + assertEquals(Block.GRASS_BLOCK, batch.getBlock(1000, 1, 0)); + } + + @Test + public void testJoinOverwrite() { + RelativeBlockBatch batch1 = new RelativeBlockBatch(); + RelativeBlockBatch batch2 = new RelativeBlockBatch(); + + batch1.setBlock(0, 0, 0, Block.STONE); + batch2.setBlock(0, 0, 0, Block.GRASS_BLOCK); + + batch1.join(batch2); + assertEquals(Block.GRASS_BLOCK, batch1.getBlock(0, 0, 0)); + } + + @Test + public void testJoinNoOverwrite() { + RelativeBlockBatch batch1 = new RelativeBlockBatch(); + RelativeBlockBatch batch2 = new RelativeBlockBatch(); + + batch1.setBlock(0, 0, 0, Block.STONE); + batch2.setBlock(0, 1, 0, Block.GRASS_BLOCK); + + batch1.join(batch2); + assertEquals(Block.STONE, batch1.getBlock(0, 0, 0)); + assertEquals(Block.GRASS_BLOCK, batch1.getBlock(0, 1, 0)); + } + + @Test + public void testDiff() { + RelativeBlockBatch batch1 = new RelativeBlockBatch(); + RelativeBlockBatch batch2 = new RelativeBlockBatch(); + + batch1.setBlock(0, 0, 0, Block.STONE); + batch1.setBlock(0, 2, 0, Block.STONE); + batch2.setBlock(0, 0, 0, Block.GRASS_BLOCK); + batch2.setBlock(0, 1, 0, Block.GRASS_BLOCK); + + RelativeBlockBatch diff = batch2.diff(batch1); + assertEquals(Block.GRASS_BLOCK, diff.getBlock(0, 1, 0)); + assertEquals(Block.GRASS_BLOCK, diff.getBlock(0, 0, 0)); + assertEquals(Block.AIR, diff.getBlock(0, 2, 0)); + } +} \ No newline at end of file