From 40516d17a90e9a537cd84a71e22e933345386525 Mon Sep 17 00:00:00 2001 From: themode Date: Thu, 22 Oct 2020 22:44:52 +0200 Subject: [PATCH] Removed try-catch in DynamicChunk and track manipulation of the buffer to prevent synchronization issue --- .../server/instance/DynamicChunk.java | 117 +++++++++--------- .../server/utils/binary/BinaryReader.java | 5 +- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/main/java/net/minestom/server/instance/DynamicChunk.java b/src/main/java/net/minestom/server/instance/DynamicChunk.java index d34e37124..a06cb7763 100644 --- a/src/main/java/net/minestom/server/instance/DynamicChunk.java +++ b/src/main/java/net/minestom/server/instance/DynamicChunk.java @@ -309,73 +309,78 @@ public class DynamicChunk extends Chunk { // Run in the scheduler thread pool MinecraftServer.getSchedulerManager().buildTask(() -> { synchronized (this) { - try { - // VERSION DATA - final int dataFormatVersion = reader.readInteger(); - final int dataProtocol = reader.readInteger(); + // Track changes in the buffer + { + final boolean changed = reader.available() != length; + Check.stateCondition(changed, + "The number of readable bytes changed, be sure to do not manipulate the buffer until the end of the reading."); + } - if (dataFormatVersion != DATA_FORMAT_VERSION) { - throw new UnsupportedOperationException( - "You are parsing an old version of the chunk format, please contact the developer: " + dataFormatVersion); - } + // VERSION DATA + final int dataFormatVersion = reader.readInteger(); + final int dataProtocol = reader.readInteger(); - // INDEX DATA - // Used for blocks data - Object2ShortMap typeToIndexMap = null; + if (dataFormatVersion != DATA_FORMAT_VERSION) { + throw new UnsupportedOperationException( + "You are parsing an old version of the chunk format, please contact the developer: " + dataFormatVersion); + } - // Get if the chunk has data indexes (used for blocks data) - final boolean hasDataIndex = reader.readBoolean(); - if (hasDataIndex) { - // Get the data indexes which will be used to read all the individual data - typeToIndexMap = SerializableData.readDataIndexes(reader); - } + // INDEX DATA + // Used for blocks data + Object2ShortMap typeToIndexMap = null; - // CHUNK DATA - // Chunk data - final boolean hasChunkData = reader.readBoolean(); - if (hasChunkData) { - SerializableData serializableData = new SerializableDataImpl(); - serializableData.readSerializedData(reader, typeToIndexMap); - } + // Get if the chunk has data indexes (used for blocks data) + final boolean hasDataIndex = reader.readBoolean(); + if (hasDataIndex) { + // Get the data indexes which will be used to read all the individual data + typeToIndexMap = SerializableData.readDataIndexes(reader); + } - // Biomes - for (int i = 0; i < BIOME_COUNT; i++) { - final byte id = reader.readByte(); - this.biomes[i] = BIOME_MANAGER.getById(id); - } + // CHUNK DATA + // Chunk data + final boolean hasChunkData = reader.readBoolean(); + if (hasChunkData) { + SerializableData serializableData = new SerializableDataImpl(); + serializableData.readSerializedData(reader, typeToIndexMap); + } - // Loop for all blocks in the chunk - while (true) { - // Position - final short index = reader.readShort(); - final byte x = ChunkUtils.blockIndexToChunkPositionX(index); - final short y = ChunkUtils.blockIndexToChunkPositionY(index); - final byte z = ChunkUtils.blockIndexToChunkPositionZ(index); + // Biomes + for (int i = 0; i < BIOME_COUNT; i++) { + final byte id = reader.readByte(); + this.biomes[i] = BIOME_MANAGER.getById(id); + } - // Block type - final short blockStateId = reader.readShort(); - final short customBlockId = reader.readShort(); + // Loop for all blocks in the chunk + while (reader.available() > 0) { + // Position + final short index = reader.readShort(); + final byte x = ChunkUtils.blockIndexToChunkPositionX(index); + final short y = ChunkUtils.blockIndexToChunkPositionY(index); + final byte z = ChunkUtils.blockIndexToChunkPositionZ(index); - // Data - SerializableData data = null; - { - final boolean hasBlockData = reader.readBoolean(); - // Data deserializer - if (hasBlockData) { - // Read the data with the deserialized index map - data = new SerializableDataImpl(); - data.readSerializedData(reader, typeToIndexMap); - } + // Block type + final short blockStateId = reader.readShort(); + final short customBlockId = reader.readShort(); + + // Data + SerializableData data = null; + { + final boolean hasBlockData = reader.readBoolean(); + // Data deserializer + if (hasBlockData) { + // Read the data with the deserialized index map + data = new SerializableDataImpl(); + data.readSerializedData(reader, typeToIndexMap); } + } - UNSAFE_setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId)); - } - } catch (IndexOutOfBoundsException e) { - // Finished reading - if (callback != null) { - callback.accept(this); - } + UNSAFE_setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId)); + } + + // Finished reading + if (callback != null) { + callback.accept(this); } } }).schedule(); diff --git a/src/main/java/net/minestom/server/utils/binary/BinaryReader.java b/src/main/java/net/minestom/server/utils/binary/BinaryReader.java index 43e53fdff..0c6ea3582 100644 --- a/src/main/java/net/minestom/server/utils/binary/BinaryReader.java +++ b/src/main/java/net/minestom/server/utils/binary/BinaryReader.java @@ -16,8 +16,9 @@ import java.io.InputStream; import java.util.UUID; /** - * Class used to read from a byte array - * WARNING: not thread-safe + * Class used to read from a byte array. + *

+ * WARNING: not thread-safe. */ public class BinaryReader extends InputStream {