fix block chunk data allocating on write to disk
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-03 19:02:35 -04:00
parent 4458c9e266
commit d7868d0ccc
7 changed files with 125 additions and 69 deletions

View File

@ -200,6 +200,9 @@ public class BlockChunkData implements BlockMeshgenData {
* @return The type at that position * @return The type at that position
*/ */
public short getType(int x, int y, int z){ public short getType(int x, int y, int z){
if(this.homogenousValue != BlockChunkData.NOT_HOMOGENOUS){
return this.homogenousValue;
}
if(this.type == null){ if(this.type == null){
this.allocateFromHomogenous(); this.allocateFromHomogenous();
} }
@ -214,10 +217,12 @@ public class BlockChunkData implements BlockMeshgenData {
* @param type The type * @param type The type
*/ */
public void setType(int x, int y, int z, short 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.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 * @param type The type
*/ */
public void setType(int x, int y, int z, int 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.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 * @param metadata The metadata
*/ */
public void setMetadata(int x, int y, int z, short 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.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 * @param metadata The metadata
*/ */
public void setMetadata(int x, int y, int z, int 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.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 * @return The metadata at that position
*/ */
public short getMetadata(int x, int y, int z){ public short getMetadata(int x, int y, int z){
if(this.homogenousValue != BlockChunkData.NOT_HOMOGENOUS){
return 0;
}
if(this.metadata == null){ if(this.metadata == null){
this.allocateFromHomogenous(); this.allocateFromHomogenous();
} }

View File

@ -29,7 +29,9 @@ import electrosphere.util.math.HashUtils;
*/ */
public class ClientBlockManager { public class ClientBlockManager {
//queues messages from server /**
* queues messages from server
*/
List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>(); List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
/** /**
@ -47,10 +49,14 @@ public class ClientBlockManager {
*/ */
public static final int FAILED_REQUEST_THRESHOLD = 500; 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; 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); 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; BlockChunkCache blockCache;
//The world data for the client /**
* The world data for the client
*/
ClientWorldData clientWorldData; ClientWorldData clientWorldData;
//The queue of block chunk data to be buffered to gpu //The queue of block chunk data to be buffered to gpu

View File

@ -214,7 +214,9 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
message.getvoxelZ(), message.getvoxelZ(),
message.getblockType() message.getblockType()
); );
data.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS); if(data.getHomogenousValue() != message.getblockType()){
data.setHomogenousValue(BlockChunkData.NOT_HOMOGENOUS);
}
} }
} }
// //

View File

@ -6,9 +6,8 @@ import io.github.studiorailgun.CircularByteBuffer;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List; 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. * 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 * The queue of incoming messages that have been parsed
*/ */
LinkedList<NetworkMessage> incomingMessageQueue = new LinkedList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
/** /**
* The queue of outgoing messages that have yet to be sent * The queue of outgoing messages that have yet to be sent
*/ */
LinkedList<NetworkMessage> outgoingMessageQueue = new LinkedList<NetworkMessage>(); CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
/** /**
* Message object pool * Message object pool
@ -60,6 +59,11 @@ public class NetworkParser {
*/ */
byte[] readBuffer = new byte[READ_BLOCK_SIZE]; byte[] readBuffer = new byte[READ_BLOCK_SIZE];
/**
* The outgoing byte buffer
*/
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>();
/** /**
* The number of bytes read * The number of bytes read
*/ */
@ -70,11 +74,6 @@ public class NetworkParser {
* Otherwise, will not release when the message is sent. * Otherwise, will not release when the message is sent.
*/ */
boolean releaseOnSend = true; 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 //parse byte queue for messages
//for each message, append to clientIncomingMessageQueue //for each message, append to clientIncomingMessageQueue
NetworkMessage newMessage; NetworkMessage newMessage;
lock.lock();
while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteBuffer,this.pool))!=null){ while((newMessage = NetworkMessage.parseBytestreamForMessage(incomingByteBuffer,this.pool))!=null){
incomingMessageQueue.add(newMessage); 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 * @throws IOException Thrown if a message fails to serialize or the output stream fails to write
*/ */
public void pushMessagesOut() throws IOException { public void pushMessagesOut() throws IOException {
lock.lock();
for(NetworkMessage message : outgoingMessageQueue){ for(NetworkMessage message : outgoingMessageQueue){
outgoingMessageQueue.remove(message);
outgoingStream.write(message.getRawBytes()); outgoingStream.write(message.getRawBytes());
if(this.releaseOnSend){ if(this.releaseOnSend){
this.pool.release(message); 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 * @return true if there is message in the queue, false otherwise
*/ */
public boolean hasIncomingMessaage(){ public boolean hasIncomingMessaage(){
lock.lock(); return incomingMessageQueue.size() > 0;
boolean rVal = incomingMessageQueue.size() > 0;
lock.unlock();
return rVal;
} }
/** /**
@ -143,10 +135,7 @@ public class NetworkParser {
* @return The message * @return The message
*/ */
public NetworkMessage popIncomingMessage(){ public NetworkMessage popIncomingMessage(){
lock.lock(); return incomingMessageQueue.remove(0);
NetworkMessage rVal = incomingMessageQueue.remove(0);
lock.unlock();
return rVal;
} }
/** /**
@ -154,9 +143,7 @@ public class NetworkParser {
* @param message The message * @param message The message
*/ */
public void addOutgoingMessage(NetworkMessage message){ public void addOutgoingMessage(NetworkMessage message){
lock.lock();
outgoingMessageQueue.add(message); outgoingMessageQueue.add(message);
lock.unlock();
} }
/** /**
@ -164,9 +151,7 @@ public class NetworkParser {
* @param messages The list to copy the incoming messages to * @param messages The list to copy the incoming messages to
*/ */
public void copyIncomingMessages(List<NetworkMessage> messages){ public void copyIncomingMessages(List<NetworkMessage> messages){
lock.lock();
messages.addAll(incomingMessageQueue); messages.addAll(incomingMessageQueue);
lock.unlock();
} }
/** /**
@ -174,9 +159,7 @@ public class NetworkParser {
* @param messages The list to copy the outgoing messages to * @param messages The list to copy the outgoing messages to
*/ */
public void copyOutgoingMessages(List<NetworkMessage> messages){ public void copyOutgoingMessages(List<NetworkMessage> messages){
lock.lock();
messages.addAll(outgoingMessageQueue); messages.addAll(outgoingMessageQueue);
lock.unlock();
} }
/** /**

View File

@ -32,6 +32,21 @@ public class ServerBlockChunkDiskMap {
*/ */
static final String BLOCK_DATA_DIR = "/block/"; 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 * The map of world position+chunk type to the file that actually houses that information
*/ */
@ -138,26 +153,42 @@ public class ServerBlockChunkDiskMap {
//parse //parse
if(rawData != null){ if(rawData != null){
ByteBuffer buffer = ByteBuffer.wrap(rawData); 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 = 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.setWorldX(worldX);
rVal.setWorldY(worldY); rVal.setWorldY(worldY);
rVal.setWorldZ(worldZ); rVal.setWorldZ(worldZ);
@ -186,13 +217,32 @@ public class ServerBlockChunkDiskMap {
//generate binary for the file //generate binary for the file
short[] type = chunkData.getType(); short[] type = chunkData.getType();
short[] metadata = chunkData.getMetadata(); short[] metadata = chunkData.getMetadata();
ByteBuffer buffer = ByteBuffer.allocate(BlockChunkData.TOTAL_DATA_WIDTH * 2 * 2);
ShortBuffer shortView = buffer.asShortBuffer(); //allocate buffer
for(int i = 0; i < BlockChunkData.TOTAL_DATA_WIDTH; i++){ ByteBuffer buffer = null;
shortView.put(type[i]); 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 //compress
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();

View File

@ -119,11 +119,10 @@ public class ServerBlockChunkGenerationThread implements Runnable {
} }
//generate if it does not exist //generate if it does not exist
if(chunk == null){ if(chunk == null){
chunk = BlockChunkData.allocate(); chunk = new BlockChunkData();
chunk.setWorldX(worldX); chunk.setWorldX(worldX);
chunk.setWorldY(worldY); chunk.setWorldY(worldY);
chunk.setWorldZ(worldZ); chunk.setWorldZ(worldZ);
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ); ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ);
} }
if(chunk != null){ if(chunk != null){

View File

@ -125,7 +125,7 @@ public class ServerBlockManager {
} }
//generate if it does not exist //generate if it does not exist
if(returnedChunk == null){ if(returnedChunk == null){
returnedChunk = BlockChunkData.allocate(); returnedChunk = new BlockChunkData();
returnedChunk.setWorldX(worldX); returnedChunk.setWorldX(worldX);
returnedChunk.setWorldY(worldY); returnedChunk.setWorldY(worldY);
returnedChunk.setWorldZ(worldZ); returnedChunk.setWorldZ(worldZ);