diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 8e73d634..141804ae 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1195,6 +1195,7 @@ Fix viewport loading (11/30/2024) Water spawner firing on repeat +Convert server side fluid storage to using buffers diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java index 4dbba524..79056200 100644 --- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java @@ -399,41 +399,39 @@ public class TerrainProtocol implements ServerProtocolTemplate { //The length along each access of the chunk data. Typically, should be at least 17. //Because CHUNK_SIZE is 16, 17 adds the necessary extra value. Each chunk needs the value of the immediately following position to generate //chunk data that connects seamlessly to the next chunk. - int xWidth = chunk.getWeights().length; - int yWidth = chunk.getWeights()[0].length; - int zWidth = chunk.getWeights()[0][0].length; + int dataLength = chunk.getWeights().limit(); - ByteBuffer buffer = ByteBuffer.allocate(xWidth*yWidth*zWidth*(4+4+4+4)); + ByteBuffer buffer = ByteBuffer.allocate(dataLength*(4+4+4+4)); FloatBuffer floatView = buffer.asFloatBuffer(); - for(int x = 0; x < xWidth; x++){ - for(int y = 0; y < yWidth; y++){ - for(int z = 0; z < zWidth; z++){ - floatView.put(chunk.getWeights()[x][y][z]); + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ + for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ + floatView.put(chunk.getWeight(x, y, z)); } } } - for(int x = 0; x < xWidth; x++){ - for(int y = 0; y < yWidth; y++){ - for(int z = 0; z < zWidth; z++){ - floatView.put(chunk.getVelocityX()[x][y][z]); + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ + for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ + floatView.put(chunk.getVelocityX(x, y, z)); } } } - for(int x = 0; x < xWidth; x++){ - for(int y = 0; y < yWidth; y++){ - for(int z = 0; z < zWidth; z++){ - floatView.put(chunk.getVelocityY()[x][y][z]); + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ + for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ + floatView.put(chunk.getVelocityY(x, y, z)); } } } - for(int x = 0; x < xWidth; x++){ - for(int y = 0; y < yWidth; y++){ - for(int z = 0; z < zWidth; z++){ - floatView.put(chunk.getVelocityZ()[x][y][z]); + for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ + for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ + for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ + floatView.put(chunk.getVelocityZ(x, y, z)); } } } diff --git a/src/main/java/electrosphere/server/fluid/diskmap/FluidDiskMap.java b/src/main/java/electrosphere/server/fluid/diskmap/FluidDiskMap.java index dc6df11d..fee635c6 100644 --- a/src/main/java/electrosphere/server/fluid/diskmap/FluidDiskMap.java +++ b/src/main/java/electrosphere/server/fluid/diskmap/FluidDiskMap.java @@ -105,39 +105,35 @@ public class FluidDiskMap { ByteBuffer buffer = ByteBuffer.wrap(rawData); FloatBuffer floatView = buffer.asFloatBuffer(); int DIM = ServerTerrainChunk.CHUNK_DIMENSION; - float[][][] weights = new float[DIM][DIM][DIM]; - float[][][] velocityX = new float[DIM][DIM][DIM]; - float[][][] velocityY = new float[DIM][DIM][DIM]; - float[][][] velocityZ = new float[DIM][DIM][DIM]; + rVal = new ServerFluidChunk(worldX, worldY, worldZ); for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - weights[x][y][z] = floatView.get(); + rVal.setWeight(x, y, z, floatView.get()); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - velocityX[x][y][z] = floatView.get(); + rVal.setVelocityX(x, y, z, floatView.get()); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - velocityY[x][y][z] = floatView.get(); + rVal.setVelocityY(x, y, z, floatView.get()); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - velocityZ[x][y][z] = floatView.get(); + rVal.setVelocityZ(x, y, z, floatView.get()); } } } - rVal = new ServerFluidChunk(worldX, worldY, worldZ, weights, velocityX, velocityY, velocityZ); } } return rVal; @@ -158,38 +154,34 @@ public class FluidDiskMap { fileName = chunkKey + ".dat"; } //generate binary for the file - float[][][] weights = fluidChunk.getWeights(); - float[][][] velocityX = fluidChunk.getVelocityX(); - float[][][] velocityY = fluidChunk.getVelocityY(); - float[][][] velocityZ = fluidChunk.getVelocityZ(); int DIM = ServerTerrainChunk.CHUNK_DIMENSION; ByteBuffer buffer = ByteBuffer.allocate(DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4 + DIM * DIM * DIM * 4); FloatBuffer floatView = buffer.asFloatBuffer(); for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - floatView.put(weights[x][y][z]); + floatView.put(fluidChunk.getWeight(x, y, z)); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - floatView.put(velocityX[x][y][z]); + floatView.put(fluidChunk.getVelocityX(x,y,z)); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - floatView.put(velocityY[x][y][z]); + floatView.put(fluidChunk.getVelocityY(x,y,z)); } } } for(int x = 0; x < DIM; x++){ for(int y = 0; y < DIM; y++){ for(int z = 0; z < DIM; z++){ - floatView.put(velocityZ[x][y][z]); + floatView.put(fluidChunk.getVelocityZ(x,y,z)); } } } diff --git a/src/main/java/electrosphere/server/fluid/generation/DefaultFluidGenerator.java b/src/main/java/electrosphere/server/fluid/generation/DefaultFluidGenerator.java index 34c978df..27054093 100644 --- a/src/main/java/electrosphere/server/fluid/generation/DefaultFluidGenerator.java +++ b/src/main/java/electrosphere/server/fluid/generation/DefaultFluidGenerator.java @@ -2,17 +2,12 @@ package electrosphere.server.fluid.generation; import electrosphere.server.fluid.manager.ServerFluidChunk; import electrosphere.server.fluid.models.FluidModel; -import electrosphere.server.terrain.manager.ServerTerrainChunk; public class DefaultFluidGenerator implements FluidGenerator { @Override public ServerFluidChunk generateChunk(int worldX, int worldY, int worldZ) { - float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; - float[][][] velocityX = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; - float[][][] velocityY = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; - float[][][] velocityZ = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; - ServerFluidChunk chunk = new ServerFluidChunk(worldX, worldY, worldZ, weights, velocityX, velocityY, velocityZ); + ServerFluidChunk chunk = new ServerFluidChunk(worldX, worldY, worldZ); return chunk; } diff --git a/src/main/java/electrosphere/server/fluid/manager/ServerFluidChunk.java b/src/main/java/electrosphere/server/fluid/manager/ServerFluidChunk.java index 1aba187b..847ffa2b 100644 --- a/src/main/java/electrosphere/server/fluid/manager/ServerFluidChunk.java +++ b/src/main/java/electrosphere/server/fluid/manager/ServerFluidChunk.java @@ -1,8 +1,13 @@ package electrosphere.server.fluid.manager; +import java.nio.FloatBuffer; + import org.joml.Vector3f; import org.joml.Vector3i; +import org.lwjgl.BufferUtils; + +import electrosphere.server.terrain.manager.ServerTerrainChunk; /** @@ -12,19 +17,19 @@ public class ServerFluidChunk { int worldX, worldY, worldZ; - float[][][] weights; - float[][][] velocityX; - float[][][] velocityY; - float[][][] velocityZ; + FloatBuffer weights; + FloatBuffer velocityX; + FloatBuffer velocityY; + FloatBuffer velocityZ; public ServerFluidChunk( int worldX, int worldY, int worldZ, - float[][][] weights, - float[][][] velocityX, - float[][][] velocityY, - float[][][] velocityZ + FloatBuffer weights, + FloatBuffer velocityX, + FloatBuffer velocityY, + FloatBuffer velocityZ ) { this.worldX = worldX; this.worldY = worldY; @@ -35,6 +40,20 @@ public class ServerFluidChunk { this.velocityZ = velocityZ; } + public ServerFluidChunk( + int worldX, + int worldY, + int worldZ + ) { + this.worldX = worldX; + this.worldY = worldY; + this.worldZ = worldZ; + this.weights = BufferUtils.createFloatBuffer(ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION); + this.velocityX = BufferUtils.createFloatBuffer(ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION); + this.velocityY = BufferUtils.createFloatBuffer(ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION); + this.velocityZ = BufferUtils.createFloatBuffer(ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION); + } + public int getWorldX() { return worldX; } @@ -55,7 +74,7 @@ public class ServerFluidChunk { return new Vector3i(worldX,worldY,worldZ); } - public float[][][] getWeights() { + public FloatBuffer getWeights() { return weights; } @@ -76,7 +95,7 @@ public class ServerFluidChunk { * @return The weight of the specified voxel */ public float getWeight(int x, int y, int z){ - return weights[x][y][z]; + return weights.get(this.IX(x,y,z)); } /** @@ -87,54 +106,94 @@ public class ServerFluidChunk { * @param weight The weight */ public void setWeight(int x, int y, int z, float weight){ - weights[x][y][z] = weight; + weights.put(this.IX(x,y,z),weight); } //get velocity x - public float[][][] getVelocityX() { + public FloatBuffer getVelocityX() { return velocityX; } + public float getVelocityX(int x, int y, int z){ + return velocityX.get(this.IX(x, y, z)); + } + //set velocity x - public void setVelocityX(float[][][] velocityX) { + public void setVelocityX(FloatBuffer velocityX) { this.velocityX = velocityX; } + public void setVelocityX(int x, int y, int z, float velocity){ + this.velocityX.put(this.IX(x,y,z),velocity); + } + //get velocity y - public float[][][] getVelocityY() { + public FloatBuffer getVelocityY() { return velocityY; } + + public float getVelocityY(int x, int y, int z){ + return velocityY.get(this.IX(x, y, z)); + } //set velocity y - public void setVelocityY(float[][][] velocityY) { + public void setVelocityY(FloatBuffer velocityY) { this.velocityY = velocityY; } + public void setVelocityY(int x, int y, int z, float velocity){ + this.velocityY.put(this.IX(x,y,z),velocity); + } + //get velocity z - public float[][][] getVelocityZ() { + public FloatBuffer getVelocityZ() { return velocityZ; } + public float getVelocityZ(int x, int y, int z){ + return velocityZ.get(this.IX(x, y, z)); + } + //set velocity z - public void setVelocityZ(float[][][] velocityZ) { + public void setVelocityZ(FloatBuffer velocityZ) { this.velocityZ = velocityZ; } + public void setVelocityZ(int x, int y, int z, float velocity){ + this.velocityZ.put(this.IX(x,y,z),velocity); + } + //get a velocity at a given x, y and z as a Vector3f public Vector3f getVelocity(int x, int y, int z){ - return new Vector3f(velocityX[x][y][z],velocityY[x][y][z],velocityZ[x][y][z]); + int index = this.IX(x,y,z); + return new Vector3f( + velocityX.get(index), + velocityY.get(index), + velocityZ.get(index) + ); } //set a velocity at a given x, y, and z given three ints public void setVelocity(int x, int y, int z, float velX, float velY, float velZ){ - velocityX[x][y][z] = velX; - velocityY[x][y][z] = velY; - velocityZ[x][y][z] = velZ; + int index = this.IX(x,y,z); + velocityX.put(index, velX); + velocityY.put(index, velY); + velocityZ.put(index, velZ); + } + + /** + * Gets the inddex into the buffer + * @param x The x position + * @param y The y position + * @param z The z position + * @return The index + */ + public int IX(int x, int y, int z){ + return x * ServerTerrainChunk.CHUNK_DIMENSION * ServerTerrainChunk.CHUNK_DIMENSION + y * ServerTerrainChunk.CHUNK_DIMENSION + z; } - } diff --git a/src/main/java/electrosphere/server/fluid/simulator/cellularautomata/FluidCellularAutomataSimulator.java b/src/main/java/electrosphere/server/fluid/simulator/cellularautomata/FluidCellularAutomataSimulator.java index 1b85b494..61c4321d 100644 --- a/src/main/java/electrosphere/server/fluid/simulator/cellularautomata/FluidCellularAutomataSimulator.java +++ b/src/main/java/electrosphere/server/fluid/simulator/cellularautomata/FluidCellularAutomataSimulator.java @@ -16,7 +16,6 @@ public class FluidCellularAutomataSimulator implements ServerFluidSimulator { @Override public boolean simulate(ServerFluidChunk fluidChunk, ServerTerrainChunk terrainChunk, int worldX, int worldY, int worldZ) { - float[][][] weights = fluidChunk.getWeights(); float[][][] terrainWeights = terrainChunk.getWeights(); //if true, alerts the server data cell to broadcast a new update message to all clients within it @@ -25,13 +24,13 @@ public class FluidCellularAutomataSimulator implements ServerFluidSimulator { for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){ for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){ for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){ - if(weights[x][y][z] <= 0){ + if(fluidChunk.getWeight(x, y, z) <= 0){ continue; } else { - if(y > 0 && weights[x][y-1][z] < MAX_WEIGHT){ + if(y > 0 && fluidChunk.getWeight(x, y - 1, z) < MAX_WEIGHT){ update = true; - weights[x][y][z] -= GRAVITY_DIFF; - weights[x][y-1][z] += GRAVITY_DIFF; + fluidChunk.setWeight(x, y, z, fluidChunk.getWeight(x, y, z) - GRAVITY_DIFF); + fluidChunk.setWeight(x, y - 1, z, fluidChunk.getWeight(x, y - 1, z) + GRAVITY_DIFF); } else { //propagate sideways int[] offsetX = new int[]{-1,1,0,0}; @@ -43,12 +42,12 @@ public class FluidCellularAutomataSimulator implements ServerFluidSimulator { realZ > 0 && realZ < ServerTerrainChunk.CHUNK_DIMENSION - 1 ){ if( - weights[realX][y][realZ] < weights[x][y][z] && + fluidChunk.getWeight(realX, y, realZ) < fluidChunk.getWeight(x, y, z) && terrainWeights[realX][y][realZ] < MAX_WEIGHT ){ update = true; - weights[x][y][z] -= GRAVITY_DIFF; - weights[realX][y][realZ] += GRAVITY_DIFF; + fluidChunk.setWeight(x, y, z, fluidChunk.getWeight(x, y, z) - GRAVITY_DIFF); + fluidChunk.setWeight(realX, y, realZ, fluidChunk.getWeight(realX, y, realZ) + GRAVITY_DIFF); } } }