diff --git a/src/main/java/electrosphere/client/terrain/cache/ChunkData.java b/src/main/java/electrosphere/client/terrain/cache/ChunkData.java index 74373287..4ad9ca94 100644 --- a/src/main/java/electrosphere/client/terrain/cache/ChunkData.java +++ b/src/main/java/electrosphere/client/terrain/cache/ChunkData.java @@ -90,6 +90,14 @@ public class ChunkData { this.homogenousValue = homogenousValue; } + /** + * Creates a chunk data object + */ + public ChunkData(){ + this.voxelWeight = new float[ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE]; + this.voxelType = new int[ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE]; + } + /** * Gets the voxel type array in this container @@ -193,6 +201,17 @@ public class ChunkData { return voxelWeight[localX][localY][localZ]; } + /** + * Sets the weight of a voxel at a poisiton + * @param localX The x coordinate + * @param localY The y coordinate + * @param localZ The z coordinate + * @param weight THe value + */ + public void setWeight(int localX, int localY, int localZ, float weight){ + voxelWeight[localX][localY][localZ] = weight; + } + /** * Gets the type of a voxel at a position * @param localPosition The local position @@ -202,6 +221,17 @@ public class ChunkData { return getType(localPosition.x,localPosition.y,localPosition.z); } + /** + * Sets the type of a voxel at a position + * @param localX The x coordinate + * @param localY The y coordinate + * @param localZ The z coordinate + * @param type The type value + */ + public void setType(int localX, int localY, int localZ, int type){ + voxelType[localX][localY][localZ] = type; + } + /** * Gets the type of a voxel at a position * @param localX The x coordinate @@ -271,5 +301,27 @@ public class ChunkData { return homogenousValue; } + public void setWorldX(int worldX) { + this.worldX = worldX; + } + + public void setWorldY(int worldY) { + this.worldY = worldY; + } + + public void setWorldZ(int worldZ) { + this.worldZ = worldZ; + } + + public void setStride(int stride) { + this.stride = stride; + } + + public void setHomogenousValue(int homogenousValue) { + this.homogenousValue = homogenousValue; + } + + + } diff --git a/src/main/java/electrosphere/client/terrain/data/TerrainChunkDataPool.java b/src/main/java/electrosphere/client/terrain/data/TerrainChunkDataPool.java index 825acef2..d844d513 100644 --- a/src/main/java/electrosphere/client/terrain/data/TerrainChunkDataPool.java +++ b/src/main/java/electrosphere/client/terrain/data/TerrainChunkDataPool.java @@ -4,6 +4,8 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.ReentrantLock; +import electrosphere.client.terrain.cache.ChunkData; + /** * Pools allocated terrain chunk data objects */ @@ -12,7 +14,12 @@ public class TerrainChunkDataPool { /** * Structure to store not-in-use objects */ - static List pool = new LinkedList(); + static List meshPool = new LinkedList(); + + /** + * Structure to store not-in-use objects + */ + static List dataPool = new LinkedList(); /** * Lock for thread-safeing operations @@ -23,11 +30,11 @@ public class TerrainChunkDataPool { * Gets a terrain chunk object from the pool. Allocates if no free one is available. * @return A terrain chunk object of the requested type */ - public static TerrainChunkData get(){ + public static TerrainChunkData getMesh(){ TerrainChunkData rVal = null; lock.lock(); - if(pool.size() > 0){ - rVal = pool.remove(0); + if(meshPool.size() > 0){ + rVal = meshPool.remove(0); } else { rVal = new TerrainChunkData(); } @@ -41,7 +48,33 @@ public class TerrainChunkDataPool { */ public static void release(TerrainChunkData data){ lock.lock(); - TerrainChunkDataPool.pool.add(data); + TerrainChunkDataPool.meshPool.add(data); + lock.unlock(); + } + + /** + * Gets a terrain chunk object from the pool. Allocates if no free one is available. + * @return A terrain chunk object of the requested type + */ + public static ChunkData getData(){ + ChunkData rVal = null; + lock.lock(); + if(dataPool.size() > 0){ + rVal = dataPool.remove(0); + } else { + rVal = new ChunkData(); + } + lock.unlock(); + return rVal; + } + + /** + * Releases a terrain chunk data object back into the pool + * @param data The object to release + */ + public static void release(ChunkData data){ + lock.lock(); + TerrainChunkDataPool.dataPool.add(data); lock.unlock(); } @@ -50,7 +83,7 @@ public class TerrainChunkDataPool { * @return The size of the chunk pool */ public static int getPoolSize(){ - return pool.size(); + return meshPool.size(); } } diff --git a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java index 2e433c45..0abfaf60 100644 --- a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java +++ b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java @@ -151,38 +151,8 @@ public class ClientTerrainManager { ); } break; case SENDREDUCEDCHUNKDATA: { - ChunkData data = new ChunkData(message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution(), message.gethomogenousValue()); - if(message.gethomogenousValue() == ChunkData.NOT_HOMOGENOUS){ - int[][][] values = new int[ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE]; - float[][][] weights = new float[ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE][ChunkData.CHUNK_DATA_SIZE]; - ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData()); - FloatBuffer floatBuffer = buffer.asFloatBuffer(); - for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){ - for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){ - for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){ - weights[x][y][z] = floatBuffer.get(); - } - } - } - IntBuffer intView = buffer.asIntBuffer(); - intView.position(floatBuffer.position()); - int firstType = -1; - boolean homogenous = true; - for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){ - for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){ - for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){ - values[x][y][z] = intView.get(); - if(firstType == -1){ - firstType = values[x][y][z]; - } else if(homogenous && firstType == values[x][y][z]){ - homogenous = false; - } - } - } - } - data.setVoxelType(values); - data.setVoxelWeight(weights); - } + ChunkData data = (ChunkData)message.getExtraData().get(0); + message.getExtraData().clear(); if(message.getchunkResolution() == ChunkData.NO_STRIDE && terrainCache.containsChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ(), ChunkData.NO_STRIDE)){ //this is a full-res chunk, and we already had this chunk in cache //need to flag foliage cell to update these positions given that we have changed terrain values diff --git a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java index 9264f1e5..e18f70c1 100644 --- a/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/common/CommonEntityUtils.java @@ -1,5 +1,7 @@ package electrosphere.entity.types.common; +import java.util.stream.Collectors; + import org.joml.Quaterniond; import org.joml.Vector3d; import org.ode4j.ode.DBody; @@ -772,6 +774,13 @@ public class CommonEntityUtils { public static Entity clientSpawnBasicObject(String type){ CommonEntityType rawType = Globals.gameConfigCurrent.getObjectTypeMap().getType(type); Entity rVal = EntityCreationUtils.createClientSpatialEntity(); + + if(rawType == null){ + String message = "Failed to lookup type: " + type + "\n" + + Globals.gameConfigCurrent.getObjectTypeMap().getTypes().stream().map((CommonEntityType typeObj) -> typeObj.getId()).collect(Collectors.toList()) + + ""; + throw new Error(message); + } // // //Common entity transforms diff --git a/src/main/java/electrosphere/net/client/ClientNetworking.java b/src/main/java/electrosphere/net/client/ClientNetworking.java index 80c931e2..95952f34 100644 --- a/src/main/java/electrosphere/net/client/ClientNetworking.java +++ b/src/main/java/electrosphere/net/client/ClientNetworking.java @@ -1,6 +1,8 @@ package electrosphere.net.client; import electrosphere.client.block.BlockChunkData; +import electrosphere.client.terrain.cache.ChunkData; +import electrosphere.client.terrain.data.TerrainChunkDataPool; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.mem.BlockChunkPool; @@ -206,6 +208,56 @@ public class ClientNetworking implements Runnable { buff.get(); } }); + parser.registerCustomParser(TypeBytes.MESSAGE_TYPE_TERRAIN, TypeBytes.TERRAIN_MESSAGE_TYPE_SENDREDUCEDCHUNKDATA, (NetworkMessage message, ByteBuffer buff) -> { + TerrainMessage castMessage = (TerrainMessage)message; + //get meta data + castMessage.setworldX(buff.getInt()); + castMessage.setworldY(buff.getInt()); + castMessage.setworldZ(buff.getInt()); + castMessage.setchunkResolution(buff.getInt()); + castMessage.sethomogenousValue(buff.getInt()); + + //construct extra data + ChunkData chunk = TerrainChunkDataPool.getData(); + chunk.setWorldX(castMessage.getworldX()); + chunk.setWorldY(castMessage.getworldY()); + chunk.setWorldZ(castMessage.getworldZ()); + chunk.setStride(castMessage.getchunkResolution()); + chunk.setHomogenousValue(castMessage.gethomogenousValue()); + + //get main data blob + if(castMessage.gethomogenousValue() == BlockChunkData.NOT_HOMOGENOUS){ + for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){ + for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){ + for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){ + chunk.setWeight(x, y, z, buff.getFloat()); + } + } + } + int firstType = -1; + boolean homogenous = true; + for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){ + for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){ + for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){ + int typeCurr = buff.getInt(); + chunk.setType(x, y, z, typeCurr); + if(firstType == -1){ + firstType = typeCurr; + } else if(homogenous && firstType == typeCurr){ + homogenous = false; + } + } + } + } + } else { + buff.get(); + } + + //attach extra data + List extraData = new LinkedList(); + extraData.add(chunk); + castMessage.setExtraData(extraData); + }); diff --git a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java index 048ca419..592d8e8a 100644 --- a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java @@ -277,7 +277,12 @@ public class EntityProtocol implements ClientProtocolTemplate { LoggerInterface.loggerNetworking.DEBUG("[CLIENT] Spawn object " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ()); //spawn item String objectType = message.getentitySubtype(); - Entity newlySpawnedEntity = CommonEntityUtils.clientSpawnBasicObject(objectType); + Entity newlySpawnedEntity = null; + try { + newlySpawnedEntity = CommonEntityUtils.clientSpawnBasicObject(objectType); + } catch (Error e){ + throw new Error(message.getentityID() + " " + objectType, e); + } //position ClientEntityUtils.initiallyPositionEntity( newlySpawnedEntity, diff --git a/src/main/java/electrosphere/net/parser/net/message/TerrainMessage.java b/src/main/java/electrosphere/net/parser/net/message/TerrainMessage.java index 0c4b8d47..f5eecf41 100644 --- a/src/main/java/electrosphere/net/parser/net/message/TerrainMessage.java +++ b/src/main/java/electrosphere/net/parser/net/message/TerrainMessage.java @@ -813,14 +813,12 @@ public class TerrainMessage extends NetworkMessage { } TerrainMessage rVal = (TerrainMessage)pool.get(MessageType.TERRAIN_MESSAGE); rVal.messageType = TerrainMessageType.SENDREDUCEDCHUNKDATA; - rVal.setworldX(byteBuffer.getInt()); - rVal.setworldY(byteBuffer.getInt()); - rVal.setworldZ(byteBuffer.getInt()); - rVal.setchunkResolution(byteBuffer.getInt()); - rVal.sethomogenousValue(byteBuffer.getInt()); - if(chunkDatalen > 0){ - rVal.setchunkData(ByteStreamUtils.popByteArrayFromByteBuffer(byteBuffer, chunkDatalen)); + short pair = (short)((TypeBytes.MESSAGE_TYPE_TERRAIN << 4) & TypeBytes.TERRAIN_MESSAGE_TYPE_SENDREDUCEDCHUNKDATA); + BiConsumer customParser = customParserMap.get(pair); + if(customParser == null){ + throw new Error("Custom parser undefined for message pair!"); } + customParser.accept(rVal,byteBuffer); return rVal; } 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 56d2f773..de4e02c3 100644 --- a/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java +++ b/src/main/java/electrosphere/net/parser/net/raw/NetworkParser.java @@ -1,7 +1,7 @@ -package electrosphere.net.parser.net.raw; - -import electrosphere.net.parser.net.message.MessagePool; -import electrosphere.net.parser.net.message.NetworkMessage; +package electrosphere.net.parser.net.raw; + +import electrosphere.net.parser.net.message.MessagePool; +import electrosphere.net.parser.net.message.NetworkMessage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; diff --git a/src/main/java/electrosphere/net/parser/util/ByteStreamUtils.java b/src/main/java/electrosphere/net/parser/util/ByteStreamUtils.java index af0eb9c9..0ee54063 100644 --- a/src/main/java/electrosphere/net/parser/util/ByteStreamUtils.java +++ b/src/main/java/electrosphere/net/parser/util/ByteStreamUtils.java @@ -1,7 +1,7 @@ -package electrosphere.net.parser.util; - -import io.github.studiorailgun.CircularByteBuffer; - +package electrosphere.net.parser.util; + +import io.github.studiorailgun.CircularByteBuffer; + import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; diff --git a/src/net/terrain.json b/src/net/terrain.json index 0dab7854..6b7645cc 100644 --- a/src/net/terrain.json +++ b/src/net/terrain.json @@ -249,6 +249,7 @@ { "messageName" : "SendReducedChunkData", "description" : "Sends chunk data to the client", + "customParser" : true, "data" : [ "worldX", "worldY",