From d7868d0ccc38835c7b9cb0b0494f9c014f4ff313 Mon Sep 17 00:00:00 2001 From: austin Date: Sat, 3 May 2025 19:02:35 -0400 Subject: [PATCH] fix block chunk data allocating on write to disk --- .../client/block/BlockChunkData.java | 30 ++++-- .../client/block/ClientBlockManager.java | 16 ++- .../net/client/protocol/TerrainProtocol.java | 4 +- .../net/parser/net/raw/NetworkParser.java | 39 ++----- .../diskmap/ServerBlockChunkDiskMap.java | 100 +++++++++++++----- .../ServerBlockChunkGenerationThread.java | 3 +- .../block/manager/ServerBlockManager.java | 2 +- 7 files changed, 125 insertions(+), 69 deletions(-) diff --git a/src/main/java/electrosphere/client/block/BlockChunkData.java b/src/main/java/electrosphere/client/block/BlockChunkData.java index de2bef7d..9d7a9fe6 100644 --- a/src/main/java/electrosphere/client/block/BlockChunkData.java +++ b/src/main/java/electrosphere/client/block/BlockChunkData.java @@ -200,6 +200,9 @@ public class BlockChunkData implements BlockMeshgenData { * @return The type at that position */ public short getType(int x, int y, int z){ + if(this.homogenousValue != BlockChunkData.NOT_HOMOGENOUS){ + return this.homogenousValue; + } if(this.type == null){ this.allocateFromHomogenous(); } @@ -214,10 +217,12 @@ public class BlockChunkData implements BlockMeshgenData { * @param type The type */ public void setType(int x, int y, int z, short type){ - if(this.type == null){ + if(this.type == null && this.homogenousValue != type){ this.allocateFromHomogenous(); } - this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = type; + if(this.type != null){ + this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = type; + } } /** @@ -228,10 +233,12 @@ public class BlockChunkData implements BlockMeshgenData { * @param type The type */ public void setType(int x, int y, int z, int type){ - if(this.type == null){ + if(this.type == null && this.homogenousValue != type){ this.allocateFromHomogenous(); } - this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = (short)type; + if(this.type != null){ + this.type[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = (short)type; + } } /** @@ -242,10 +249,12 @@ public class BlockChunkData implements BlockMeshgenData { * @param metadata The metadata */ public void setMetadata(int x, int y, int z, short metadata){ - if(this.metadata == null){ + if(this.metadata == null && metadata != 0){ this.allocateFromHomogenous(); } - this.metadata[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = metadata; + if(this.metadata != null){ + this.metadata[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = metadata; + } } /** @@ -256,10 +265,12 @@ public class BlockChunkData implements BlockMeshgenData { * @param metadata The metadata */ public void setMetadata(int x, int y, int z, int metadata){ - if(this.metadata == null){ + if(this.metadata == null && metadata != 0){ this.allocateFromHomogenous(); } - this.metadata[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = (short)metadata; + if(this.metadata != null){ + this.metadata[x * CHUNK_DATA_WIDTH * CHUNK_DATA_WIDTH + z * CHUNK_DATA_WIDTH + y] = (short)metadata; + } } /** @@ -270,6 +281,9 @@ public class BlockChunkData implements BlockMeshgenData { * @return The metadata at that position */ public short getMetadata(int x, int y, int z){ + if(this.homogenousValue != BlockChunkData.NOT_HOMOGENOUS){ + return 0; + } if(this.metadata == null){ this.allocateFromHomogenous(); } diff --git a/src/main/java/electrosphere/client/block/ClientBlockManager.java b/src/main/java/electrosphere/client/block/ClientBlockManager.java index 33ea5d1c..4d8f81f1 100644 --- a/src/main/java/electrosphere/client/block/ClientBlockManager.java +++ b/src/main/java/electrosphere/client/block/ClientBlockManager.java @@ -29,7 +29,9 @@ import electrosphere.util.math.HashUtils; */ public class ClientBlockManager { - //queues messages from server + /** + * queues messages from server + */ List messageQueue = new LinkedList(); /** @@ -47,10 +49,14 @@ public class ClientBlockManager { */ public static final int FAILED_REQUEST_THRESHOLD = 500; - //The interpolation ratio of block + /** + * The interpolation ratio of block + */ public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO; - //caches chunks from server + /** + * caches chunks from server + */ static final int CACHE_SIZE = 2500 + (int)(ClientDrawCellManager.FULL_RES_DIST * 10) + (int)(ClientDrawCellManager.HALF_RES_DIST * 10); /** @@ -63,7 +69,9 @@ public class ClientBlockManager { */ BlockChunkCache blockCache; - //The world data for the client + /** + * The world data for the client + */ ClientWorldData clientWorldData; //The queue of block chunk data to be buffered to gpu diff --git a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java index 14f4d24e..dff10c2a 100644 --- a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java @@ -214,7 +214,9 @@ public class TerrainProtocol implements ClientProtocolTemplate { message.getvoxelZ(), message.getblockType() ); - data.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS); + if(data.getHomogenousValue() != message.getblockType()){ + data.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS); + } } } // diff --git a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java index fc98988f..87a15f71 100644 --- a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java +++ b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java @@ -6,9 +6,8 @@ import io.github.studiorailgun.CircularByteBuffer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.LinkedList; import java.util.List; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.CopyOnWriteArrayList; /** * The main message parser. This is used to serialize/deserialize messages to/from the provided streams. @@ -38,12 +37,12 @@ public class NetworkParser { /** * The queue of incoming messages that have been parsed */ - LinkedList incomingMessageQueue = new LinkedList(); + CopyOnWriteArrayList incomingMessageQueue = new CopyOnWriteArrayList(); /** * The queue of outgoing messages that have yet to be sent */ - LinkedList outgoingMessageQueue = new LinkedList(); + CopyOnWriteArrayList outgoingMessageQueue = new CopyOnWriteArrayList(); /** * Message object pool @@ -60,6 +59,11 @@ public class NetworkParser { */ byte[] readBuffer = new byte[READ_BLOCK_SIZE]; + /** + * The outgoing byte buffer + */ + CopyOnWriteArrayList outgoingByteQueue = new CopyOnWriteArrayList(); + /** * The number of bytes read */ @@ -70,11 +74,6 @@ public class NetworkParser { * Otherwise, will not release when the message is sent. */ boolean releaseOnSend = true; - - /** - * Lock for thread-safing the parser - */ - ReentrantLock lock = new ReentrantLock(); /** @@ -104,11 +103,9 @@ public class NetworkParser { //parse byte queue for messages //for each message, append to clientIncomingMessageQueue NetworkMessage newMessage; - lock.lock(); while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteBuffer,this.pool))!=null){ incomingMessageQueue.add(newMessage); } - lock.unlock(); } /** @@ -116,15 +113,13 @@ public class NetworkParser { * @throws IOException Thrown if a message fails to serialize or the output stream fails to write */ public void pushMessagesOut() throws IOException { - lock.lock(); for(NetworkMessage message : outgoingMessageQueue){ + outgoingMessageQueue.remove(message); outgoingStream.write(message.getRawBytes()); if(this.releaseOnSend){ this.pool.release(message); } } - outgoingMessageQueue.clear(); - lock.unlock(); } /** @@ -132,10 +127,7 @@ public class NetworkParser { * @return true if there is message in the queue, false otherwise */ public boolean hasIncomingMessaage(){ - lock.lock(); - boolean rVal = incomingMessageQueue.size() > 0; - lock.unlock(); - return rVal; + return incomingMessageQueue.size() > 0; } /** @@ -143,10 +135,7 @@ public class NetworkParser { * @return The message */ public NetworkMessage popIncomingMessage(){ - lock.lock(); - NetworkMessage rVal = incomingMessageQueue.remove(0); - lock.unlock(); - return rVal; + return incomingMessageQueue.remove(0); } /** @@ -154,9 +143,7 @@ public class NetworkParser { * @param message The message */ public void addOutgoingMessage(NetworkMessage message){ - lock.lock(); outgoingMessageQueue.add(message); - lock.unlock(); } /** @@ -164,9 +151,7 @@ public class NetworkParser { * @param messages The list to copy the incoming messages to */ public void copyIncomingMessages(List messages){ - lock.lock(); messages.addAll(incomingMessageQueue); - lock.unlock(); } /** @@ -174,9 +159,7 @@ public class NetworkParser { * @param messages The list to copy the outgoing messages to */ public void copyOutgoingMessages(List messages){ - lock.lock(); messages.addAll(outgoingMessageQueue); - lock.unlock(); } /** diff --git a/src/main/java/electrosphere/server/physics/block/diskmap/ServerBlockChunkDiskMap.java b/src/main/java/electrosphere/server/physics/block/diskmap/ServerBlockChunkDiskMap.java index ddfd6e66..62a87061 100644 --- a/src/main/java/electrosphere/server/physics/block/diskmap/ServerBlockChunkDiskMap.java +++ b/src/main/java/electrosphere/server/physics/block/diskmap/ServerBlockChunkDiskMap.java @@ -32,6 +32,21 @@ public class ServerBlockChunkDiskMap { */ static final String BLOCK_DATA_DIR = "/block/"; + /** + * 1 x 4 int that stores whether it is a homogenous chunk or not + */ + static final int FILE_HEADER = 4; + + /** + * Header value for it being a non-homogenous chunk + */ + static final int HEADER_NON_HOMOGENOUS = 0; + + /** + * Header value for it being a homogenous chunk + */ + static final int HEADER_HOMOGENOUS = 1; + /** * The map of world position+chunk type to the file that actually houses that information */ @@ -138,26 +153,42 @@ public class ServerBlockChunkDiskMap { //parse if(rawData != null){ ByteBuffer buffer = ByteBuffer.wrap(rawData); - ShortBuffer shortView = buffer.asShortBuffer(); - short[] type = new short[BlockChunkData.TOTAL_DATA_WIDTH]; - short[] metadata = new short[BlockChunkData.TOTAL_DATA_WIDTH]; - short firstType = -1; - boolean homogenous = true; - for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ - type[i] = shortView.get(); - if(firstType == -1){ - firstType = type[i]; - } else if(homogenous && firstType == type[i]){ - homogenous = false; - } - } - for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ - metadata[i] = shortView.get(); - } rVal = new BlockChunkData(); - rVal.setType(type); - rVal.setMetadata(metadata); - rVal.setHomogenousValue(homogenous ? firstType : BlockChunkData.NOT_HOMOGENOUS); + + + int headerHomogenousType = buffer.getInt(); + if(headerHomogenousType == HEADER_NON_HOMOGENOUS){ + + //read a non-homogenous chunk + ShortBuffer shortView = buffer.asShortBuffer(); + short[] type = new short[BlockChunkData.TOTAL_DATA_WIDTH]; + short[] metadata = new short[BlockChunkData.TOTAL_DATA_WIDTH]; + short firstType = -1; + boolean homogenous = true; + for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ + type[i] = shortView.get(); + if(firstType == -1){ + firstType = type[i]; + } else if(homogenous && firstType == type[i]){ + homogenous = false; + } + } + for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ + metadata[i] = shortView.get(); + } + + + rVal.setType(type); + rVal.setMetadata(metadata); + rVal.setHomogenousValue(homogenous ? firstType : BlockChunkData.NOT_HOMOGENOUS); + } else { + + //read a homogenous chunk + short homogenousValue = buffer.getShort(); + rVal.setHomogenousValue(homogenousValue); + } + + //set metadata rVal.setWorldX(worldX); rVal.setWorldY(worldY); rVal.setWorldZ(worldZ); @@ -186,13 +217,32 @@ public class ServerBlockChunkDiskMap { //generate binary for the file short[] type = chunkData.getType(); short[] metadata = chunkData.getMetadata(); - ByteBuffer buffer = ByteBuffer.allocate(BlockChunkData.TOTAL_DATA_WIDTH * 2 * 2); - ShortBuffer shortView = buffer.asShortBuffer(); - for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ - shortView.put(type[i]); + + //allocate buffer + ByteBuffer buffer = null; + if(chunkData.getHomogenousValue() == BlockChunkData.NOT_HOMOGENOUS){ + buffer = ByteBuffer.allocate(ServerBlockChunkDiskMap.FILE_HEADER + BlockChunkData.TOTAL_DATA_WIDTH * 2 * 2); + } else { + buffer = ByteBuffer.allocate(ServerBlockChunkDiskMap.FILE_HEADER + 2); } - for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ - shortView.put(metadata[i]); + + //push data + if(chunkData.getHomogenousValue() == BlockChunkData.NOT_HOMOGENOUS){ + //put header + buffer.putInt(HEADER_NON_HOMOGENOUS); + //put data + ShortBuffer shortView = buffer.asShortBuffer(); + for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ + shortView.put(type[i]); + } + for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ + shortView.put(metadata[i]); + } + } else { + //put header + buffer.putInt(HEADER_HOMOGENOUS); + //put data + buffer.putShort(chunkData.getHomogenousValue()); } //compress ByteArrayOutputStream out = new ByteArrayOutputStream(); diff --git a/src/main/java/electrosphere/server/physics/block/manager/ServerBlockChunkGenerationThread.java b/src/main/java/electrosphere/server/physics/block/manager/ServerBlockChunkGenerationThread.java index 4e51cac6..452f6f41 100644 --- a/src/main/java/electrosphere/server/physics/block/manager/ServerBlockChunkGenerationThread.java +++ b/src/main/java/electrosphere/server/physics/block/manager/ServerBlockChunkGenerationThread.java @@ -119,11 +119,10 @@ public class ServerBlockChunkGenerationThread implements Runnable { } //generate if it does not exist if(chunk == null){ - chunk = BlockChunkData.allocate(); + chunk = new BlockChunkData(); chunk.setWorldX(worldX); chunk.setWorldY(worldY); chunk.setWorldZ(worldZ); - ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ); } if(chunk != null){ diff --git a/src/main/java/electrosphere/server/physics/block/manager/ServerBlockManager.java b/src/main/java/electrosphere/server/physics/block/manager/ServerBlockManager.java index 3cb367b3..dbb13c9d 100644 --- a/src/main/java/electrosphere/server/physics/block/manager/ServerBlockManager.java +++ b/src/main/java/electrosphere/server/physics/block/manager/ServerBlockManager.java @@ -125,7 +125,7 @@ public class ServerBlockManager { } //generate if it does not exist if(returnedChunk == null){ - returnedChunk = BlockChunkData.allocate(); + returnedChunk = new BlockChunkData(); returnedChunk.setWorldX(worldX); returnedChunk.setWorldY(worldY); returnedChunk.setWorldZ(worldZ);