From 032017380092051b7142b5c02fd43e68858b037e Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 5 Nov 2024 14:47:08 -0500 Subject: [PATCH] Add stride to reduced endpoint --- .../client/terrain/cache/ChunkData.java | 5 ++ .../net/client/protocol/TerrainProtocol.java | 4 ++ .../net/server/protocol/TerrainProtocol.java | 67 ++++++++++++++++++- .../generation/DefaultChunkGenerator.java | 2 +- .../generation/OverworldChunkGenerator.java | 2 +- .../TestGenerationChunkGenerator.java | 2 +- .../generation/interfaces/ChunkGenerator.java | 3 +- .../manager/ChunkGenerationThread.java | 10 ++- .../terrain/manager/ServerTerrainManager.java | 8 ++- 9 files changed, 94 insertions(+), 9 deletions(-) diff --git a/src/main/java/electrosphere/client/terrain/cache/ChunkData.java b/src/main/java/electrosphere/client/terrain/cache/ChunkData.java index 4036d6a0..5f094f24 100644 --- a/src/main/java/electrosphere/client/terrain/cache/ChunkData.java +++ b/src/main/java/electrosphere/client/terrain/cache/ChunkData.java @@ -12,6 +12,11 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk; */ public class ChunkData { + /** + * No stride + */ + public static final int NO_STRIDE = 0; + //The size of a chunk in virtual data public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION; //The size of the data passed into marching cubes/transvoxel algorithm to get a fully connected and seamless chunk diff --git a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java index cdd606f2..aee25351 100644 --- a/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/TerrainProtocol.java @@ -47,6 +47,10 @@ public class TerrainProtocol implements ClientProtocolTemplate { LoggerInterface.loggerNetworking.DEBUG("(Client) Received terrain at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); Globals.clientTerrainManager.attachTerrainMessage(message); } break; + case SENDREDUCEDCHUNKDATA: { + LoggerInterface.loggerNetworking.DEBUG("(Client) Received terrain at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ() + " " + message.getchunkResolution()); + Globals.clientTerrainManager.attachTerrainMessage(message); + } break; case UPDATEVOXEL: { // //find what all drawcells might be updated by this voxel update diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java index 99b1d4f8..610199d3 100644 --- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java @@ -7,6 +7,7 @@ import java.util.function.Consumer; import org.joml.Vector3d; +import electrosphere.client.terrain.cache.ChunkData; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.net.parser.net.message.TerrainMessage; @@ -32,6 +33,12 @@ public class TerrainProtocol implements ServerProtocolTemplate { ); return null; } + case REQUESTREDUCEDCHUNKDATA: { + sendWorldSubChunkAsyncStrided(connectionHandler, + message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution() + ); + return null; + } default: { } break; } @@ -185,7 +192,65 @@ public class TerrainProtocol implements ServerProtocolTemplate { }; //request chunk - realm.getServerWorldData().getServerTerrainManager().getChunkAsync(worldX, worldY, worldZ, onLoad); + realm.getServerWorldData().getServerTerrainManager().getChunkAsync(worldX, worldY, worldZ, ChunkData.NO_STRIDE, onLoad); + + Globals.profiler.endCpuSample(); + } + + /** + * Sends a subchunk to the client + * @param connectionHandler The connection handler + * @param worldX the world x + * @param worldY the world y + * @param worldZ the world z + * @param stride The stride of the data + */ + static void sendWorldSubChunkAsyncStrided(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ, int stride){ + Globals.profiler.beginAggregateCpuSample("TerrainProtocol(server).sendWorldSubChunk"); + + // System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY()); + Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer()); + if(realm.getServerWorldData().getServerTerrainManager() == null){ + return; + } + + Consumer onLoad = (ServerTerrainChunk chunk) -> { + //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; + + ByteBuffer buffer = ByteBuffer.allocate(xWidth*yWidth*zWidth*(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]); + } + } + } + + IntBuffer intView = buffer.asIntBuffer(); + intView.position(floatView.position()); + + for(int x = 0; x < xWidth; x++){ + for(int y = 0; y < yWidth; y++){ + for(int z = 0; z < zWidth; z++){ + intView.put(chunk.getValues()[x][y][z]); + } + } + } + + // System.out.println("(Server) Send terrain at " + worldX + " " + worldY + " " + worldZ); + LoggerInterface.loggerNetworking.DEBUG("(Server) Send terrain at " + worldX + " " + worldY + " " + worldZ); + connectionHandler.addMessagetoOutgoingQueue(TerrainMessage.constructsendChunkDataMessage(worldX, worldY, worldZ, buffer.array())); + }; + + //request chunk + realm.getServerWorldData().getServerTerrainManager().getChunkAsync(worldX, worldY, worldZ, stride, onLoad); Globals.profiler.endCpuSample(); } diff --git a/src/main/java/electrosphere/server/terrain/generation/DefaultChunkGenerator.java b/src/main/java/electrosphere/server/terrain/generation/DefaultChunkGenerator.java index c3c2518b..2a5f5b5a 100644 --- a/src/main/java/electrosphere/server/terrain/generation/DefaultChunkGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/DefaultChunkGenerator.java @@ -22,7 +22,7 @@ public class DefaultChunkGenerator implements ChunkGenerator { } @Override - public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) { + public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) { //Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap. //Hence, width should actually be chunk dimension + 1 float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION]; diff --git a/src/main/java/electrosphere/server/terrain/generation/OverworldChunkGenerator.java b/src/main/java/electrosphere/server/terrain/generation/OverworldChunkGenerator.java index 15bd5d21..6674257a 100644 --- a/src/main/java/electrosphere/server/terrain/generation/OverworldChunkGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/OverworldChunkGenerator.java @@ -28,7 +28,7 @@ public class OverworldChunkGenerator implements ChunkGenerator { } @Override - public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) { + public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) { ServerTerrainChunk returnedChunk; //Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap. //Hence, width should actually be chunk dimension + 1 diff --git a/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java b/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java index 669c6fb1..aa299212 100644 --- a/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java @@ -65,7 +65,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator { } @Override - public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) { + public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) { Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk"); ServerTerrainChunk rVal = null; float[][][] weights; diff --git a/src/main/java/electrosphere/server/terrain/generation/interfaces/ChunkGenerator.java b/src/main/java/electrosphere/server/terrain/generation/interfaces/ChunkGenerator.java index bb002835..d6e5afa3 100644 --- a/src/main/java/electrosphere/server/terrain/generation/interfaces/ChunkGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/interfaces/ChunkGenerator.java @@ -13,9 +13,10 @@ public interface ChunkGenerator { * @param worldX The x component * @param worldY The y component * @param worldZ The z component + * @param stride The stride of the data * @return The chunk */ - public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ); + public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride); /** * Sets the terrain model for the generation algorithm diff --git a/src/main/java/electrosphere/server/terrain/manager/ChunkGenerationThread.java b/src/main/java/electrosphere/server/terrain/manager/ChunkGenerationThread.java index b66556d3..5446f56e 100644 --- a/src/main/java/electrosphere/server/terrain/manager/ChunkGenerationThread.java +++ b/src/main/java/electrosphere/server/terrain/manager/ChunkGenerationThread.java @@ -51,6 +51,11 @@ public class ChunkGenerationThread implements Runnable { * The world z coordinate */ int worldZ; + + /** + * The stride of the data + */ + int stride; /** * The work to do once the chunk is available @@ -65,6 +70,7 @@ public class ChunkGenerationThread implements Runnable { * @param worldX The world x coordinate * @param worldY The world y coordinate * @param worldZ The world z coordinate + * @param stride The stride of the data * @param onLoad The work to do once the chunk is available */ public ChunkGenerationThread( @@ -72,6 +78,7 @@ public class ChunkGenerationThread implements Runnable { ServerChunkCache chunkCache, ChunkGenerator chunkGenerator, int worldX, int worldY, int worldZ, + int stride, Consumer onLoad ){ this.chunkDiskMap = chunkDiskMap; @@ -80,6 +87,7 @@ public class ChunkGenerationThread implements Runnable { this.worldX = worldX; this.worldY = worldY; this.worldZ = worldZ; + this.stride = stride; this.onLoad = onLoad; } @@ -99,7 +107,7 @@ public class ChunkGenerationThread implements Runnable { } //generate if it does not exist if(chunk == null){ - chunk = chunkGenerator.generateChunk(worldX, worldY, worldZ); + chunk = chunkGenerator.generateChunk(worldX, worldY, worldZ, stride); } if(chunk != null){ chunkCache.add(worldX, worldY, worldZ, chunk); diff --git a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java index 2c9adec1..3a3ad4b9 100644 --- a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java @@ -1,5 +1,6 @@ package electrosphere.server.terrain.manager; +import electrosphere.client.terrain.cache.ChunkData; import electrosphere.engine.Globals; import electrosphere.game.server.world.ServerWorldData; import electrosphere.server.terrain.diskmap.ChunkDiskMap; @@ -242,7 +243,7 @@ public class ServerTerrainManager { } //generate if it does not exist if(returnedChunk == null){ - returnedChunk = chunkGenerator.generateChunk(worldX, worldY, worldZ); + returnedChunk = chunkGenerator.generateChunk(worldX, worldY, worldZ, ChunkData.NO_STRIDE); } this.chunkCache.add(worldX, worldY, worldZ, returnedChunk); } @@ -255,11 +256,12 @@ public class ServerTerrainManager { * @param worldX The world x position * @param worldY The world y position * @param worldZ The world z position + * @param stride The stride of the data * @param onLoad The logic to run once the chunk is available */ - public void getChunkAsync(int worldX, int worldY, int worldZ, Consumer onLoad){ + public void getChunkAsync(int worldX, int worldY, int worldZ, int stride, Consumer onLoad){ Globals.profiler.beginCpuSample("ServerTerrainManager.getChunkAsync"); - this.chunkExecutorService.submit(new ChunkGenerationThread(chunkDiskMap, chunkCache, chunkGenerator, worldX, worldY, worldZ, onLoad)); + this.chunkExecutorService.submit(new ChunkGenerationThread(chunkDiskMap, chunkCache, chunkGenerator, worldX, worldY, worldZ, stride, onLoad)); Globals.profiler.endCpuSample(); }