voxelImprovements #5
@ -12,6 +12,11 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public class ChunkData {
 | 
					public class ChunkData {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * No stride
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static final int NO_STRIDE = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //The size of a chunk in virtual data
 | 
					    //The size of a chunk in virtual data
 | 
				
			||||||
    public static final int CHUNK_SIZE = ServerTerrainChunk.CHUNK_DIMENSION;
 | 
					    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
 | 
					    //The size of the data passed into marching cubes/transvoxel algorithm to get a fully connected and seamless chunk
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,10 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
 | 
				
			|||||||
                LoggerInterface.loggerNetworking.DEBUG("(Client) Received terrain at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
 | 
					                LoggerInterface.loggerNetworking.DEBUG("(Client) Received terrain at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
 | 
				
			||||||
                Globals.clientTerrainManager.attachTerrainMessage(message);
 | 
					                Globals.clientTerrainManager.attachTerrainMessage(message);
 | 
				
			||||||
            } break;
 | 
					            } 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: {
 | 
					            case UPDATEVOXEL: {
 | 
				
			||||||
                //
 | 
					                //
 | 
				
			||||||
                //find what all drawcells might be updated by this voxel update
 | 
					                //find what all drawcells might be updated by this voxel update
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import java.util.function.Consumer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import org.joml.Vector3d;
 | 
					import org.joml.Vector3d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import electrosphere.client.terrain.cache.ChunkData;
 | 
				
			||||||
import electrosphere.engine.Globals;
 | 
					import electrosphere.engine.Globals;
 | 
				
			||||||
import electrosphere.logger.LoggerInterface;
 | 
					import electrosphere.logger.LoggerInterface;
 | 
				
			||||||
import electrosphere.net.parser.net.message.TerrainMessage;
 | 
					import electrosphere.net.parser.net.message.TerrainMessage;
 | 
				
			||||||
@ -32,6 +33,12 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
 | 
				
			|||||||
                );
 | 
					                );
 | 
				
			||||||
                return null;
 | 
					                return null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            case REQUESTREDUCEDCHUNKDATA: {
 | 
				
			||||||
 | 
					                sendWorldSubChunkAsyncStrided(connectionHandler, 
 | 
				
			||||||
 | 
					                    message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution()
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            default: {
 | 
					            default: {
 | 
				
			||||||
            } break;
 | 
					            } break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -185,7 +192,65 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //request chunk
 | 
					        //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<ServerTerrainChunk> 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();
 | 
					        Globals.profiler.endCpuSample();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ public class DefaultChunkGenerator implements ChunkGenerator {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @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.
 | 
					        //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
 | 
					        //Hence, width should actually be chunk dimension + 1
 | 
				
			||||||
        float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
 | 
					        float[][][] weights = new float[ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION][ServerTerrainChunk.CHUNK_DIMENSION];
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ public class OverworldChunkGenerator implements ChunkGenerator {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ) {
 | 
					    public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
 | 
				
			||||||
        ServerTerrainChunk returnedChunk;
 | 
					        ServerTerrainChunk returnedChunk;
 | 
				
			||||||
        //Each chunk also needs custody of the next chunk's first values so that they can perfectly overlap.
 | 
					        //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
 | 
					        //Hence, width should actually be chunk dimension + 1
 | 
				
			||||||
 | 
				
			|||||||
@ -65,7 +65,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @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");
 | 
					        Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk");
 | 
				
			||||||
        ServerTerrainChunk rVal = null;
 | 
					        ServerTerrainChunk rVal = null;
 | 
				
			||||||
        float[][][] weights;
 | 
					        float[][][] weights;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,9 +13,10 @@ public interface ChunkGenerator {
 | 
				
			|||||||
     * @param worldX The x component
 | 
					     * @param worldX The x component
 | 
				
			||||||
     * @param worldY The y component
 | 
					     * @param worldY The y component
 | 
				
			||||||
     * @param worldZ The z component
 | 
					     * @param worldZ The z component
 | 
				
			||||||
 | 
					     * @param stride The stride of the data
 | 
				
			||||||
     * @return The chunk
 | 
					     * @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
 | 
					     * Sets the terrain model for the generation algorithm
 | 
				
			||||||
 | 
				
			|||||||
@ -52,6 +52,11 @@ public class ChunkGenerationThread implements Runnable {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    int worldZ;
 | 
					    int worldZ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The stride of the data
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    int stride;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The work to do once the chunk is available
 | 
					     * 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 worldX The world x coordinate
 | 
				
			||||||
     * @param worldY The world y coordinate
 | 
					     * @param worldY The world y coordinate
 | 
				
			||||||
     * @param worldZ The world z 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
 | 
					     * @param onLoad The work to do once the chunk is available
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public ChunkGenerationThread(
 | 
					    public ChunkGenerationThread(
 | 
				
			||||||
@ -72,6 +78,7 @@ public class ChunkGenerationThread implements Runnable {
 | 
				
			|||||||
        ServerChunkCache chunkCache,
 | 
					        ServerChunkCache chunkCache,
 | 
				
			||||||
        ChunkGenerator chunkGenerator,
 | 
					        ChunkGenerator chunkGenerator,
 | 
				
			||||||
        int worldX, int worldY, int worldZ,
 | 
					        int worldX, int worldY, int worldZ,
 | 
				
			||||||
 | 
					        int stride,
 | 
				
			||||||
        Consumer<ServerTerrainChunk> onLoad
 | 
					        Consumer<ServerTerrainChunk> onLoad
 | 
				
			||||||
    ){
 | 
					    ){
 | 
				
			||||||
        this.chunkDiskMap = chunkDiskMap;
 | 
					        this.chunkDiskMap = chunkDiskMap;
 | 
				
			||||||
@ -80,6 +87,7 @@ public class ChunkGenerationThread implements Runnable {
 | 
				
			|||||||
        this.worldX = worldX;
 | 
					        this.worldX = worldX;
 | 
				
			||||||
        this.worldY = worldY;
 | 
					        this.worldY = worldY;
 | 
				
			||||||
        this.worldZ = worldZ;
 | 
					        this.worldZ = worldZ;
 | 
				
			||||||
 | 
					        this.stride = stride;
 | 
				
			||||||
        this.onLoad = onLoad;
 | 
					        this.onLoad = onLoad;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,7 +107,7 @@ public class ChunkGenerationThread implements Runnable {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                //generate if it does not exist
 | 
					                //generate if it does not exist
 | 
				
			||||||
                if(chunk == null){
 | 
					                if(chunk == null){
 | 
				
			||||||
                    chunk = chunkGenerator.generateChunk(worldX, worldY, worldZ);
 | 
					                    chunk = chunkGenerator.generateChunk(worldX, worldY, worldZ, stride);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if(chunk != null){
 | 
					                if(chunk != null){
 | 
				
			||||||
                    chunkCache.add(worldX, worldY, worldZ, chunk);
 | 
					                    chunkCache.add(worldX, worldY, worldZ, chunk);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
package electrosphere.server.terrain.manager;
 | 
					package electrosphere.server.terrain.manager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import electrosphere.client.terrain.cache.ChunkData;
 | 
				
			||||||
import electrosphere.engine.Globals;
 | 
					import electrosphere.engine.Globals;
 | 
				
			||||||
import electrosphere.game.server.world.ServerWorldData;
 | 
					import electrosphere.game.server.world.ServerWorldData;
 | 
				
			||||||
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
 | 
					import electrosphere.server.terrain.diskmap.ChunkDiskMap;
 | 
				
			||||||
@ -242,7 +243,7 @@ public class ServerTerrainManager {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            //generate if it does not exist
 | 
					            //generate if it does not exist
 | 
				
			||||||
            if(returnedChunk == null){
 | 
					            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);
 | 
					            this.chunkCache.add(worldX, worldY, worldZ, returnedChunk);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -255,11 +256,12 @@ public class ServerTerrainManager {
 | 
				
			|||||||
     * @param worldX The world x position
 | 
					     * @param worldX The world x position
 | 
				
			||||||
     * @param worldY The world y position
 | 
					     * @param worldY The world y position
 | 
				
			||||||
     * @param worldZ The world z 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
 | 
					     * @param onLoad The logic to run once the chunk is available
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void getChunkAsync(int worldX, int worldY, int worldZ, Consumer<ServerTerrainChunk> onLoad){
 | 
					    public void getChunkAsync(int worldX, int worldY, int worldZ, int stride, Consumer<ServerTerrainChunk> onLoad){
 | 
				
			||||||
        Globals.profiler.beginCpuSample("ServerTerrainManager.getChunkAsync");
 | 
					        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();
 | 
					        Globals.profiler.endCpuSample();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user