From 93bae2508509d6a6713e085e58774c23ed3564b1 Mon Sep 17 00:00:00 2001 From: themode Date: Wed, 11 Nov 2020 07:29:07 +0100 Subject: [PATCH] Custom blocks also use a PaletteStorage object, removed StaticChunk since memory is not an issue anymore --- .../server/instance/DynamicChunk.java | 24 ++-- .../server/instance/InstanceContainer.java | 2 +- .../minestom/server/instance/StaticChunk.java | 127 ------------------ .../server/instance/block/BlockProvider.java | 6 - .../instance/palette/PaletteStorage.java | 12 +- .../packet/server/play/ChunkDataPacket.java | 14 +- 6 files changed, 26 insertions(+), 159 deletions(-) delete mode 100644 src/main/java/net/minestom/server/instance/StaticChunk.java delete mode 100644 src/main/java/net/minestom/server/instance/block/BlockProvider.java diff --git a/src/main/java/net/minestom/server/instance/DynamicChunk.java b/src/main/java/net/minestom/server/instance/DynamicChunk.java index 4a356f763..8bf1d474b 100644 --- a/src/main/java/net/minestom/server/instance/DynamicChunk.java +++ b/src/main/java/net/minestom/server/instance/DynamicChunk.java @@ -12,7 +12,6 @@ import net.minestom.server.entity.pathfinding.PFBlockDescription; import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.instance.palette.PaletteStorage; import net.minestom.server.network.packet.server.play.ChunkDataPacket; -import net.minestom.server.utils.ArrayUtils; import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; @@ -42,12 +41,9 @@ public class DynamicChunk extends Chunk { */ private static final int DATA_FORMAT_VERSION = 1; - // blocks id based on coordinate, see Chunk#getBlockIndex - // WARNING: those arrays are NOT thread-safe - // and modifying them can cause issue with block data, update, block entity and the cached chunk packet - //protected final short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; + // WARNING: not thread-safe protected PaletteStorage blockPalette = new PaletteStorage(15); - protected final short[] customBlocksId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; + protected PaletteStorage customBlockPalette = new PaletteStorage(15); // Used to get all blocks with data (no null) // Key is still chunk coordinates (see #getBlockIndex) @@ -82,13 +78,13 @@ public class DynamicChunk extends Chunk { final boolean hasBlock = blockStateId != 0 || customBlockId != 0; if (hasBlock) { this.blockPalette.setBlockAt(x, y, z, blockStateId); - this.customBlocksId[index] = customBlockId; + this.customBlockPalette.setBlockAt(x, y, z, customBlockId); } else { // Block has been deleted, clear cache and return this.blockPalette.setBlockAt(x, y, z, (short) 0); //this.blocksStateId[index] = 0; // Set to air - this.customBlocksId[index] = 0; // Remove custom block + this.customBlockPalette.setBlockAt(x, y, z, (short) 0); // Remove custom block this.blocksData.remove(index); @@ -158,15 +154,13 @@ public class DynamicChunk extends Chunk { @Override public short getCustomBlockId(int x, int y, int z) { - final int index = getBlockIndex(x, y, z); - return customBlocksId[index]; + return customBlockPalette.getBlockAt(x, y, z); } @Override protected void refreshBlockValue(int x, int y, int z, short blockStateId, short customBlockId) { - final int blockIndex = getBlockIndex(x, y, z); this.blockPalette.setBlockAt(x, y, z, blockStateId); - this.customBlocksId[blockIndex] = customBlockId; + this.customBlockPalette.setBlockAt(x, y, z, customBlockId); } @Override @@ -243,7 +237,7 @@ public class DynamicChunk extends Chunk { final int index = getBlockIndex(x, y, z); final short blockStateId = blockPalette.getBlockAt(x, y, z); - final short customBlockId = customBlocksId[index]; + final short customBlockId = customBlockPalette.getBlockAt(x, y, z); // No block at the position if (blockStateId == 0 && customBlockId == 0) @@ -381,7 +375,7 @@ public class DynamicChunk extends Chunk { fullDataPacket.chunkX = chunkX; fullDataPacket.chunkZ = chunkZ; fullDataPacket.paletteStorage = blockPalette.copy(); - fullDataPacket.customBlocksId = customBlocksId.clone(); + fullDataPacket.customBlockPaletteStorage = customBlockPalette.copy(); fullDataPacket.blockEntities = new HashSet<>(blockEntities); fullDataPacket.blocksData = new Int2ObjectOpenHashMap<>(blocksData); return fullDataPacket; @@ -392,7 +386,7 @@ public class DynamicChunk extends Chunk { public Chunk copy(int chunkX, int chunkZ) { DynamicChunk dynamicChunk = new DynamicChunk(biomes.clone(), chunkX, chunkZ); dynamicChunk.blockPalette = blockPalette.copy(); - ArrayUtils.copyToDestination(customBlocksId, dynamicChunk.customBlocksId); + dynamicChunk.customBlockPalette = customBlockPalette.copy(); dynamicChunk.blocksData.putAll(blocksData); dynamicChunk.updatableBlocks.addAll(updatableBlocks); dynamicChunk.updatableBlocksLastUpdate.putAll(updatableBlocksLastUpdate); diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 0bfa83d68..c6a7ff65b 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -581,7 +581,7 @@ public class InstanceContainer extends Instance { * @throws NullPointerException if {@code chunkSupplier} is null */ public void setChunkSupplier(@NotNull ChunkSupplier chunkSupplier) { - Check.notNull(chunkSupplier, "The chunk supplier cannot be null, you can use a StaticChunk for a lightweight implementation"); + Check.notNull(chunkSupplier, "The chunk supplier cannot be null!"); this.chunkSupplier = chunkSupplier; } diff --git a/src/main/java/net/minestom/server/instance/StaticChunk.java b/src/main/java/net/minestom/server/instance/StaticChunk.java deleted file mode 100644 index 8486b97bd..000000000 --- a/src/main/java/net/minestom/server/instance/StaticChunk.java +++ /dev/null @@ -1,127 +0,0 @@ -package net.minestom.server.instance; - -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.minestom.server.data.Data; -import net.minestom.server.instance.block.BlockProvider; -import net.minestom.server.network.packet.server.play.ChunkDataPacket; -import net.minestom.server.utils.binary.BinaryReader; -import net.minestom.server.utils.callback.OptionalCallback; -import net.minestom.server.utils.chunk.ChunkCallback; -import net.minestom.server.utils.chunk.ChunkUtils; -import net.minestom.server.world.biomes.Biome; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; - -/** - * Represents a {@link Chunk} which does not store any block, it makes use of a {@link BlockProvider} - * instead to use less memory. - *

- * Can be used for very simple chunks such as flat or others with not any random factor. - *

- * WARNING: adding blocks or anything to this chunk would not work, it is static. - */ -public class StaticChunk extends Chunk { - - protected final BlockProvider blockProvider; - - public StaticChunk(@Nullable Biome[] biomes, int chunkX, int chunkZ, - @NotNull BlockProvider blockProvider) { - super(biomes, chunkX, chunkZ, false); - this.blockProvider = blockProvider; - setReadOnly(true); - } - - @Override - public void UNSAFE_setBlock(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data, boolean updatable) { - //noop - } - - @Override - public void tick(long time, @NotNull Instance instance) { - //noop - } - - @Override - public short getBlockStateId(int x, int y, int z) { - return blockProvider.getBlockStateId(x, y, z); - } - - @Override - public short getCustomBlockId(int x, int y, int z) { - //noop - return 0; - } - - @Override - protected void refreshBlockValue(int x, int y, int z, short blockStateId, short customId) { - //noop - } - - @Override - protected void refreshBlockStateId(int x, int y, int z, short blockStateId) { - //noop - } - - @Override - public Data getBlockData(int index) { - return null; - } - - @Override - public void setBlockData(int x, int y, int z, Data data) { - //noop - } - - @NotNull - @Override - public Set getBlockEntities() { - return new HashSet<>(); - } - - @Override - public byte[] getSerializedData() { - return null; - } - - @Override - public void readChunk(@NotNull BinaryReader reader, @Nullable ChunkCallback callback) { - OptionalCallback.execute(callback, this); - } - - @NotNull - @Override - protected ChunkDataPacket createFreshPacket() { - ChunkDataPacket fullDataPacket = new ChunkDataPacket(); - fullDataPacket.biomes = biomes.clone(); - fullDataPacket.chunkX = chunkX; - fullDataPacket.chunkZ = chunkZ; - short[] blocksStateId = new short[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; - for (int i = 0; i < blocksStateId.length; i++) { - final int x = ChunkUtils.blockIndexToChunkPositionX(i); - final int y = ChunkUtils.blockIndexToChunkPositionY(i); - final int z = ChunkUtils.blockIndexToChunkPositionZ(i); - blocksStateId[i] = blockProvider.getBlockStateId(x, y, z); - } - //fullDataPacket.blocksStateId = blocksStateId; - fullDataPacket.customBlocksId = new short[0]; - fullDataPacket.blockEntities = new HashSet<>(); - fullDataPacket.blocksData = new Int2ObjectOpenHashMap<>(); - return fullDataPacket; - } - - @NotNull - @Override - public Chunk copy(int chunkX, int chunkZ) { - StaticChunk staticChunk = new StaticChunk(biomes.clone(), chunkX, chunkZ, blockProvider); - // Prevent re-writing the whole packet since it is static anyway - /*final ByteBuf packetBuffer = getFullDataPacket(); - if (packetBuffer != null) { - staticChunk.setFullDataPacket(packetBuffer); - }*/ - - return staticChunk; - } -} \ No newline at end of file diff --git a/src/main/java/net/minestom/server/instance/block/BlockProvider.java b/src/main/java/net/minestom/server/instance/block/BlockProvider.java deleted file mode 100644 index 7b054c7a2..000000000 --- a/src/main/java/net/minestom/server/instance/block/BlockProvider.java +++ /dev/null @@ -1,6 +0,0 @@ -package net.minestom.server.instance.block; - -@FunctionalInterface -public interface BlockProvider { - short getBlockStateId(int x, int y, int z); -} diff --git a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java index 50881234e..e829e2095 100644 --- a/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java +++ b/src/main/java/net/minestom/server/instance/palette/PaletteStorage.java @@ -33,6 +33,10 @@ public class PaletteStorage { final int section = y / CHUNK_SECTION_SIZE; if (sectionBlocks[section].length == 0) { + if (blockId == 0) { + return; + } + sectionBlocks[section] = new long[getSize()]; } @@ -95,18 +99,18 @@ public class PaletteStorage { long finalValue; - System.out.println("index " + index); + /*System.out.println("index " + index); System.out.println("bitIndex " + bitIndex); System.out.println("test1 " + binary(value)); - System.out.println("test2 " + binary(mask)); + System.out.println("test2 " + binary(mask));*/ { mask = mask >> bitIndex << bitIndex; - System.out.println("test3 " + binary(mask)); + //System.out.println("test3 " + binary(mask)); finalValue = value & mask >> bitIndex; } - System.out.println("final " + binary(finalValue)); + //System.out.println("final " + binary(finalValue)); /*System.out.println("data " + index + " " + bitIndex + " " + sectionIndex); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java index cb2044aff..cf8ccd965 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ChunkDataPacket.java @@ -29,7 +29,7 @@ public class ChunkDataPacket implements ServerPacket { public int chunkX, chunkZ; public PaletteStorage paletteStorage; - public short[] customBlocksId; + public PaletteStorage customBlockPaletteStorage; public Set blockEntities; public Int2ObjectMap blocksData; @@ -106,11 +106,13 @@ public class ChunkDataPacket implements ServerPacket { .setInt("y", blockPosition.getY()) .setInt("z", blockPosition.getZ()); - final short customBlockId = customBlocksId[index]; - final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId); - if (customBlock != null) { - final Data data = blocksData.get(index); - customBlock.writeBlockEntity(blockPosition, data, nbt); + if (customBlockPaletteStorage != null) { + final short customBlockId = customBlockPaletteStorage.getBlockAt(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ()); + final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId); + if (customBlock != null) { + final Data data = blocksData.get(index); + customBlock.writeBlockEntity(blockPosition, data, nbt); + } } writer.writeNBT("", nbt); }