From 4d9759c6ec6bbdae66a266004b55427701e79a1a Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 29 Apr 2025 16:55:38 -0400 Subject: [PATCH] server terrain chunk stride fix --- docs/src/progress/renderertodo.md | 2 + .../client/terrain/cells/DrawCell.java | 21 ++++++ .../client/ui/menu/debug/ImGuiDrawCell.java | 75 +++++++++++++++++++ .../ui/menu/debug/ImGuiWindowMacros.java | 4 + .../menu/debug/entity/ImGuiEntityMacros.java | 8 ++ .../net/server/protocol/TerrainProtocol.java | 6 +- .../gridded/GriddedDataCellManager.java | 11 +-- .../fluid/manager/ServerFluidManager.java | 3 +- .../physics/terrain/diskmap/ChunkDiskMap.java | 14 +++- .../manager/ChunkGenerationThread.java | 6 +- .../terrain/manager/ServerChunkCache.java | 26 +++++++ .../terrain/manager/ServerTerrainManager.java | 9 ++- 12 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 608ff056..abeb2fbf 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1592,6 +1592,8 @@ ServerBlockManager places macro data structures when generating chunks that cont Fix life trees creating state items when trees undefined in data Unhashing ivec hashed keys in chunk caches Unit tests for unhash func +Filter client entity list to terrain +Fix server loading full res chunks from disk as strided chunks diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java index 2cc052bb..069823a7 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java @@ -10,6 +10,7 @@ import electrosphere.client.terrain.cache.ChunkData; import electrosphere.engine.Globals; import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.Entity; +import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.types.terrain.TerrainChunk; import electrosphere.renderer.meshgen.TransvoxelModelGeneration; @@ -593,6 +594,26 @@ public class DrawCell { return cachedMinDistance; } } + + @Override + public String toString(){ + Vector3d entityPos = null; + if(modelEntity != null){ + entityPos = EntityUtils.getPosition(modelEntity); + } + String rVal = "" + + "worldPos: " + worldPos + "\n" + + "lod: " + lod + "\n" + + "modelEntity: " + modelEntity + "\n" + + "entityPos: " + entityPos + "\n" + + "hasRequested: " + hasRequested + "\n" + + "hasGenerated: " + hasGenerated + "\n" + + "homogenous: " + homogenous + "\n" + + "cachedMinDistance: " + cachedMinDistance + "\n" + + "" + ; + return rVal; + } } diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java new file mode 100644 index 00000000..181e7d02 --- /dev/null +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiDrawCell.java @@ -0,0 +1,75 @@ +package electrosphere.client.ui.menu.debug; + +import org.joml.Vector3i; + +import electrosphere.client.entity.camera.CameraEntityUtils; +import electrosphere.client.terrain.cache.ChunkData; +import electrosphere.client.terrain.cells.DrawCell; +import electrosphere.engine.Globals; +import electrosphere.logger.LoggerInterface; +import electrosphere.renderer.ui.imgui.ImGuiWindow; +import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback; +import imgui.ImGui; + +/** + * Debug ui for draw cells + */ +public class ImGuiDrawCell { + + /** + * Window for viewing chunk status on server and client + */ + protected static ImGuiWindow drawCellWindow; + + /** + * Creates the windows in this file + */ + protected static void createDrawCellWindows(){ + ImGuiDrawCell.createDrawCellWindow(); + } + + /** + * Client scene entity view + */ + protected static void createDrawCellWindow(){ + drawCellWindow = new ImGuiWindow("Draw Cells"); + drawCellWindow.setCallback(new ImGuiWindowCallback() { + @Override + public void exec() { + if(ImGui.button("Debug camera position")){ + Vector3i cameraWorldPos = Globals.clientWorldData.convertRealToWorldSpace(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + DrawCell cell = Globals.clientDrawCellManager.getDrawCell(cameraWorldPos.x, cameraWorldPos.y, cameraWorldPos.z); + LoggerInterface.loggerEngine.WARNING("" + cell); + + LoggerInterface.loggerEngine.WARNING("Chunk topology:"); + ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(cameraWorldPos, 1); + if(data != null){ + for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){ + String line = ""; + for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){ + int height = 0; + for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){ + if(data.getType(x, y, z) != 0){ + height = y; + } + } + line = line + String.format("%2d ",height); + } + LoggerInterface.loggerEngine.WARNING(line); + } + LoggerInterface.loggerEngine.WARNING("\n"); + } else { + LoggerInterface.loggerEngine.WARNING("Chunk not in cache! " + cameraWorldPos); + } + } + if(ImGui.button("Request terrain at camera position")){ + Vector3i cameraWorldPos = Globals.clientWorldData.convertRealToWorldSpace(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); + Globals.clientTerrainManager.requestChunk(cameraWorldPos.x, cameraWorldPos.y, cameraWorldPos.z, 1); + } + } + }); + drawCellWindow.setOpen(false); + Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(drawCellWindow); + } + +} diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiWindowMacros.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiWindowMacros.java index 8de2a590..8b8087e6 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiWindowMacros.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiWindowMacros.java @@ -53,6 +53,7 @@ public class ImGuiWindowMacros { ImGuiGriddedManager.createGriddedManagerWindows(); ImGuiMemory.createMemoryWindows(); ImGuiEditorWindows.initEditorWindows(); + ImGuiDrawCell.createDrawCellWindows(); } /** @@ -180,6 +181,9 @@ public class ImGuiWindowMacros { if(ImGui.button("Network Monitor")){ ImGuiNetworkMonitor.netMonitorWindow.setOpen(true); } + if(ImGui.button("Client Draw Cell Utils")){ + ImGuiDrawCell.drawCellWindow.setOpen(true); + } //close button if(ImGui.button("Close")){ mainDebugWindow.setOpen(false); diff --git a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java index e85498fb..af3246d6 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java @@ -26,6 +26,7 @@ import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.foliage.FoliageUtils; import electrosphere.entity.types.item.ItemUtils; +import electrosphere.entity.types.terrain.TerrainChunk; import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.game.data.foliage.type.FoliageType; import electrosphere.logger.LoggerInterface; @@ -52,6 +53,7 @@ public class ImGuiEntityMacros { private static boolean filterBasic = true; //filters out entities we probably wouldn't want to see (particles, terrain meshes, foliage cells, etc) private static boolean filterToCreatures = false; //filters the entity list to just creatures private static boolean filterToFoliage = false; //filters the entity list to just foliage + private static boolean filterToTerrain = false; //filters the entity list to just terrain //window for viewing details about an entity protected static ImGuiWindow clientEntityDetailWindow; @@ -99,6 +101,9 @@ public class ImGuiEntityMacros { if(ImGui.checkbox("Filter to Foliage", filterToFoliage)){ filterToFoliage = !filterToFoliage; } + if(ImGui.checkbox("Filter to Terrain", filterToTerrain)){ + filterToTerrain = !filterToTerrain; + } for(Entity entity : Globals.clientSceneWrapper.getScene().getEntityList()){ //filters if(filterToCreatures && !CreatureUtils.isCreature(entity)){ @@ -107,6 +112,9 @@ public class ImGuiEntityMacros { if(filterToFoliage && !FoliageUtils.isFoliage(entity)){ continue; } + if(filterToTerrain && !TerrainChunk.isTerrainEntity(entity)){ + continue; + } if(filterBasic && ( AmbientFoliage.getAmbientFoliageTree(entity) != null || diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java index ac33eb43..5f311b99 100644 --- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java @@ -65,7 +65,7 @@ public class TerrainProtocol implements ServerProtocolTemplate { LoggerInterface.loggerNetworking.DEBUG("(Server) Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); // System.out.println("Received request for terrain " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ()); TerrainProtocol.sendWorldSubChunk(connectionHandler, - message.getworldX(), message.getworldY(), message.getworldZ() + message.getworldX(), message.getworldY(), message.getworldZ(), message.getchunkResolution() ); } break; case REQUESTEDITVOXEL: { @@ -123,7 +123,7 @@ public class TerrainProtocol implements ServerProtocolTemplate { * @param worldY the world y * @param worldZ the world z */ - static void sendWorldSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){ + static void sendWorldSubChunk(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()); @@ -133,7 +133,7 @@ public class TerrainProtocol implements ServerProtocolTemplate { } //request chunk - ServerTerrainChunk chunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldX, worldY, worldZ); + ServerTerrainChunk chunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldX, worldY, worldZ, stride); //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 diff --git a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java index 9794c9c3..23b0cc2a 100644 --- a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java @@ -42,6 +42,7 @@ import electrosphere.server.pathfinding.NavMeshConstructor; import electrosphere.server.physics.block.manager.ServerBlockManager; import electrosphere.server.physics.fluid.manager.ServerFluidChunk; import electrosphere.server.physics.fluid.manager.ServerFluidManager; +import electrosphere.server.physics.terrain.manager.ServerChunkCache; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.manager.ServerTerrainManager; import electrosphere.server.physics.terrain.models.TerrainModel; @@ -340,7 +341,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager ); BlockChunkData blockChunkData = parent.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z); - ServerTerrainChunk terrainChunk = parent.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z); + ServerTerrainChunk terrainChunk = parent.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES); //create entities Entity blockEntity = EntityCreationUtils.createServerEntity(parent, realPos); @@ -784,7 +785,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager generationService.submit(() -> { try { BlockChunkData blockChunkData = realm.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z); - ServerTerrainChunk terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z); + ServerTerrainChunk terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES); targetCell.setTerrainChunk(terrainChunk); targetCell.setBlockChunk(blockChunkData); @@ -867,7 +868,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager * @return The weight of the described voxel */ public float getVoxelWeightAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition) { - return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z).getWeights()[voxelPosition.x][voxelPosition.y][voxelPosition.z]; + return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z, ServerChunkCache.STRIDE_FULL_RES).getWeights()[voxelPosition.x][voxelPosition.y][voxelPosition.z]; } @Override @@ -878,7 +879,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager * @return The type of the described voxel */ public int getVoxelTypeAtLocalPosition(Vector3i worldPosition, Vector3i voxelPosition) { - return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z).getValues()[voxelPosition.x][voxelPosition.y][voxelPosition.z]; + return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z, ServerChunkCache.STRIDE_FULL_RES).getValues()[voxelPosition.x][voxelPosition.y][voxelPosition.z]; } @Override @@ -888,7 +889,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager * @return The ServerTerrainChunk of data at that position, or null if it is out of bounds or otherwise doesn't exist */ public ServerTerrainChunk getChunkAtPosition(Vector3i worldPosition) { - return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z); + return serverTerrainManager.getChunk(worldPosition.x, worldPosition.y, worldPosition.z, ServerChunkCache.STRIDE_FULL_RES); } @Override diff --git a/src/main/java/electrosphere/server/physics/fluid/manager/ServerFluidManager.java b/src/main/java/electrosphere/server/physics/fluid/manager/ServerFluidManager.java index 2a7b5cf4..88699ebe 100644 --- a/src/main/java/electrosphere/server/physics/fluid/manager/ServerFluidManager.java +++ b/src/main/java/electrosphere/server/physics/fluid/manager/ServerFluidManager.java @@ -8,6 +8,7 @@ import electrosphere.server.physics.fluid.generation.FluidGenerator; import electrosphere.server.physics.fluid.models.FluidModel; import electrosphere.server.physics.fluid.simulator.FluidAcceleratedSimulator; import electrosphere.server.physics.fluid.simulator.ServerFluidSimulator; +import electrosphere.server.physics.terrain.manager.ServerChunkCache; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.manager.ServerTerrainManager; import electrosphere.util.FileUtils; @@ -359,7 +360,7 @@ public class ServerFluidManager { lock.lock(); ServerFluidChunk rVal = chunkGenerator.generateChunk(worldX, worldY, worldZ); ServerWorldData serverWorldData = this.parent; - ServerTerrainChunk terrainChunk = serverWorldData.getServerTerrainManager().getChunk(worldX, worldY, worldZ); + ServerTerrainChunk terrainChunk = serverWorldData.getServerTerrainManager().getChunk(worldX, worldY, worldZ, ServerChunkCache.STRIDE_FULL_RES); for(int x = ServerFluidChunk.TRUE_DATA_OFFSET; x < ServerFluidChunk.TRUE_DATA_DIM + ServerFluidChunk.TRUE_DATA_OFFSET; x++){ for(int y = ServerFluidChunk.TRUE_DATA_OFFSET; y < ServerFluidChunk.TRUE_DATA_DIM + ServerFluidChunk.TRUE_DATA_OFFSET; y++){ for(int z = ServerFluidChunk.TRUE_DATA_OFFSET; z < ServerFluidChunk.TRUE_DATA_DIM + ServerFluidChunk.TRUE_DATA_OFFSET; z++){ diff --git a/src/main/java/electrosphere/server/physics/terrain/diskmap/ChunkDiskMap.java b/src/main/java/electrosphere/server/physics/terrain/diskmap/ChunkDiskMap.java index 3cb1d3a8..2004b4eb 100644 --- a/src/main/java/electrosphere/server/physics/terrain/diskmap/ChunkDiskMap.java +++ b/src/main/java/electrosphere/server/physics/terrain/diskmap/ChunkDiskMap.java @@ -16,6 +16,7 @@ import java.util.zip.InflaterOutputStream; import electrosphere.client.terrain.cache.ChunkData; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; +import electrosphere.server.physics.terrain.manager.ServerChunkCache; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.saves.SaveUtils; import electrosphere.util.FileUtils; @@ -122,9 +123,13 @@ public class ChunkDiskMap { * @param worldX The x component * @param worldY The y component * @param worldZ The z component + * @param stride The stride of the chunk * @return True if the map contains the chunk, false otherwise */ - public boolean containsTerrainAtPosition(int worldX, int worldY, int worldZ){ + public boolean containsTerrainAtPosition(int worldX, int worldY, int worldZ, int stride){ + if(stride != ServerChunkCache.STRIDE_FULL_RES){ + throw new Error("Server chunk diskmap does not currently support non-full-res chunks! " + stride); + } lock.lock(); boolean rVal = worldPosFileMap.containsKey(getTerrainChunkKey(worldX, worldY, worldZ)); lock.unlock(); @@ -152,11 +157,14 @@ public class ChunkDiskMap { * @param worldZ The z coordinate * @return The server terrain chunk if it exists, null otherwise */ - public ServerTerrainChunk getTerrainChunk(int worldX, int worldY, int worldZ){ + public ServerTerrainChunk getTerrainChunk(int worldX, int worldY, int worldZ, int stride){ + if(stride != ServerChunkCache.STRIDE_FULL_RES){ + throw new Error("Server chunk diskmap does not currently support non-full-res chunks! " + stride); + } lock.lock(); LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ); ServerTerrainChunk rVal = null; - if(this.containsTerrainAtPosition(worldX, worldY, worldZ)){ + if(this.containsTerrainAtPosition(worldX, worldY, worldZ, stride)){ //read file String fileName = worldPosFileMap.get(ChunkDiskMap.getTerrainChunkKey(worldX, worldY, worldZ)); byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), fileName); diff --git a/src/main/java/electrosphere/server/physics/terrain/manager/ChunkGenerationThread.java b/src/main/java/electrosphere/server/physics/terrain/manager/ChunkGenerationThread.java index 11a8e5fe..d35eae1d 100644 --- a/src/main/java/electrosphere/server/physics/terrain/manager/ChunkGenerationThread.java +++ b/src/main/java/electrosphere/server/physics/terrain/manager/ChunkGenerationThread.java @@ -102,9 +102,9 @@ public class ChunkGenerationThread implements Runnable { chunk = chunkCache.get(worldX, worldY, worldZ, stride); } else { //pull from disk if it exists - if(chunkDiskMap != null){ - if(chunkDiskMap.containsTerrainAtPosition(worldX, worldY, worldZ)){ - chunk = chunkDiskMap.getTerrainChunk(worldX, worldY, worldZ); + if(chunkDiskMap != null && stride == ServerChunkCache.STRIDE_FULL_RES){ + if(chunkDiskMap.containsTerrainAtPosition(worldX, worldY, worldZ, stride)){ + chunk = chunkDiskMap.getTerrainChunk(worldX, worldY, worldZ, stride); } } //generate if it does not exist diff --git a/src/main/java/electrosphere/server/physics/terrain/manager/ServerChunkCache.java b/src/main/java/electrosphere/server/physics/terrain/manager/ServerChunkCache.java index 32aa9293..8c72c00e 100644 --- a/src/main/java/electrosphere/server/physics/terrain/manager/ServerChunkCache.java +++ b/src/main/java/electrosphere/server/physics/terrain/manager/ServerChunkCache.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Semaphore; +import electrosphere.client.terrain.cells.ClientDrawCellManager; import electrosphere.server.physics.terrain.diskmap.ChunkDiskMap; import electrosphere.util.math.HashUtils; @@ -21,6 +22,31 @@ public class ServerChunkCache { */ static final int CACHE_SIZE = 1500; + /** + * Stride for a full res chunk + */ + public static final int STRIDE_FULL_RES = ClientDrawCellManager.FULL_RES_LOD; + + /** + * Stride for a half res chunk + */ + public static final int STRIDE_HALF_RES = ClientDrawCellManager.HALF_RES_LOD; + + /** + * Stride for a quarter res chunk + */ + public static final int STRIDE_QUARTER_RES = ClientDrawCellManager.QUARTER_RES_LOD; + + /** + * Stride for a eighth res chunk + */ + public static final int STRIDE_EIGHTH_RES = ClientDrawCellManager.EIGHTH_RES_LOD; + + /** + * Stride for a sixteenth res chunk + */ + public static final int STRIDE_SIXTEENTH_RES = ClientDrawCellManager.SIXTEENTH_RES_LOD; + /** * The size of the cache */ diff --git a/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java index a0966975..454b2bb7 100644 --- a/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/physics/terrain/manager/ServerTerrainManager.java @@ -275,9 +275,10 @@ 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 * @return The ServerTerrainChunk */ - public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ){ + public ServerTerrainChunk getChunk(int worldX, int worldY, int worldZ, int stride){ Globals.profiler.beginAggregateCpuSample("ServerTerrainManager.getChunk"); //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING ServerTerrainChunk returnedChunk = null; @@ -286,8 +287,8 @@ public class ServerTerrainManager { } else { //pull from disk if it exists if(chunkDiskMap != null){ - if(chunkDiskMap.containsTerrainAtPosition(worldX, worldY, worldZ)){ - returnedChunk = chunkDiskMap.getTerrainChunk(worldX, worldY, worldZ); + if(chunkDiskMap.containsTerrainAtPosition(worldX, worldY, worldZ, stride)){ + returnedChunk = chunkDiskMap.getTerrainChunk(worldX, worldY, worldZ, stride); } } //generate if it does not exist @@ -336,7 +337,7 @@ public class ServerTerrainManager { */ public void savePositionToDisk(Vector3i position){ if(chunkDiskMap != null && chunkCache.containsChunk(position.x, position.y, position.z, ChunkData.NO_STRIDE)){ - chunkDiskMap.saveToDisk(this.getChunk(position.x, position.y, position.z)); + chunkDiskMap.saveToDisk(this.getChunk(position.x, position.y, position.z, ServerChunkCache.STRIDE_FULL_RES)); } }