server side terrain management refactoring
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-11-23 21:46:13 -05:00
parent 1b1876643d
commit 3777a9a37c
10 changed files with 118 additions and 116 deletions

View File

@ -1144,6 +1144,8 @@ Fix script entity spawn utils not spawning on max cursor distance
Block mesh generation Block mesh generation
Add asset manager support for queueing models asynchronously w/ promised path Add asset manager support for queueing models asynchronously w/ promised path
Add promised path support to queued textures Add promised path support to queued textures
Code formatting on queued asset classes
Refactoring server side of terrain management
# TODO # TODO

View File

@ -22,6 +22,11 @@ public class BlockChunkData {
*/ */
public static final float BLOCK_SIZE_MULTIPLIER = 1.0f / BLOCKS_PER_UNIT_DISTANCE; public static final float BLOCK_SIZE_MULTIPLIER = 1.0f / BLOCKS_PER_UNIT_DISTANCE;
/**
* Set if this chunk is not homogenous
*/
public static final short NOT_HOMOGENOUS = -1;
/** /**
* The type of block at a given position * The type of block at a given position
@ -34,6 +39,11 @@ public class BlockChunkData {
*/ */
short[] metadata; short[] metadata;
/**
* If this block chunk is homogenously a single value, it will be the value of this short. Otherwise is
*/
short homogenousValue = NOT_HOMOGENOUS;
/** /**
* Constructor * Constructor
*/ */
@ -41,7 +51,7 @@ public class BlockChunkData {
} }
/** /**
* Constructor * Allocates a BlockChunkData with empty values
*/ */
public static BlockChunkData allocate(){ public static BlockChunkData allocate(){
BlockChunkData rVal = new BlockChunkData(); BlockChunkData rVal = new BlockChunkData();
@ -50,6 +60,15 @@ public class BlockChunkData {
return rVal; return rVal;
} }
/**
* Allocates a BlockChunkData with a homogenous value
*/
public static BlockChunkData allocate(short homogenousValue){
BlockChunkData rVal = new BlockChunkData();
rVal.homogenousValue = homogenousValue;
return rVal;
}
/** /**
* Gets the type data for the chunk * Gets the type data for the chunk
* @return The type data * @return The type data
@ -147,5 +166,12 @@ public class BlockChunkData {
return empty; return empty;
} }
/**
* Checks if this block chunk is homogenous or not
* @return true if it is homogenous, false otherwise
*/
public boolean isHomogenous(){
return this.homogenousValue != NOT_HOMOGENOUS;
}
} }

View File

@ -10,7 +10,9 @@ import electrosphere.renderer.model.Model;
*/ */
public class QueuedModel implements QueuedAsset<Model> { public class QueuedModel implements QueuedAsset<Model> {
//true if loaded /**
* true if loaded
*/
boolean hasLoaded = false; boolean hasLoaded = false;
/** /**

View File

@ -11,13 +11,19 @@ import electrosphere.renderer.texture.Texture;
*/ */
public class QueuedTexture implements QueuedAsset<Texture> { public class QueuedTexture implements QueuedAsset<Texture> {
//true if loaded /**
* True if loaded
*/
boolean hasLoaded = false; boolean hasLoaded = false;
//the resulting texture object /**
* The resuling texture object
*/
Texture texture = null; Texture texture = null;
//data to be loaded /**
* The data to be loaded
*/
BufferedImage data; BufferedImage data;
/** /**

View File

@ -278,21 +278,21 @@ public class ClientLoading {
EntityUtils.getScale(Globals.playerCursor).set(0.2f); EntityUtils.getScale(Globals.playerCursor).set(0.2f);
//block test //block test
// Entity blockEntity = EntityCreationUtils.createClientSpatialEntity(); Entity blockEntity = EntityCreationUtils.createClientSpatialEntity();
// BlockChunkData blockChunkData = BlockChunkData.allocate(); BlockChunkData blockChunkData = BlockChunkData.allocate();
// blockChunkData.setType(0, 0, 0, 1); blockChunkData.setType(0, 0, 0, 1);
// blockChunkData.setType(1, 0, 0, 1); blockChunkData.setType(1, 0, 0, 1);
// blockChunkData.setType(0, 1, 0, 1); blockChunkData.setType(0, 1, 0, 1);
// blockChunkData.setType(1, 1, 0, 1); blockChunkData.setType(1, 1, 0, 1);
// blockChunkData.setType(0, 0, 1, 1); blockChunkData.setType(0, 0, 1, 1);
// blockChunkData.setType(1, 0, 1, 1); blockChunkData.setType(1, 0, 1, 1);
// blockChunkData.setType(0, 1, 1, 1); blockChunkData.setType(0, 1, 1, 1);
// blockChunkData.setType(1, 1, 1, 1); blockChunkData.setType(1, 1, 1, 1);
// BlockMeshData meshData = BlockMeshgen.rasterize(blockChunkData); BlockMeshData meshData = BlockMeshgen.rasterize(blockChunkData);
// String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> { String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
// return BlockMeshgen.generateBlockModel(meshData); return BlockMeshgen.generateBlockModel(meshData);
// })); }));
// EntityCreationUtils.makeEntityDrawablePreexistingModel(blockEntity, modelPath); EntityCreationUtils.makeEntityDrawablePreexistingModel(blockEntity, modelPath);
} }
static final int MAX_DRAW_CELL_WAIT = 1000; static final int MAX_DRAW_CELL_WAIT = 1000;

View File

@ -23,8 +23,10 @@ import electrosphere.util.annotation.Exclude;
*/ */
public class ChunkDiskMap { public class ChunkDiskMap {
//The map of world position+chunk type to the file that actually houses that information /**
Map<String,String> worldPosFileMap = new HashMap<String,String>(); * The map of world position+chunk type to the file that actually houses that information
*/
Map<String,String> worldPosFileMap;
/** /**
* Locks the chunk disk map for thread safety * Locks the chunk disk map for thread safety
@ -35,8 +37,8 @@ public class ChunkDiskMap {
/** /**
* Constructor * Constructor
*/ */
public ChunkDiskMap(){ private ChunkDiskMap(){
worldPosFileMap = new HashMap<String,String>();
} }
/** /**
@ -65,14 +67,24 @@ public class ChunkDiskMap {
* Initializes a diskmap based on a given save name * Initializes a diskmap based on a given save name
* @param saveName The save name * @param saveName The save name
*/ */
public void init(String saveName){ public static ChunkDiskMap init(String saveName){
ChunkDiskMap rVal = null;
LoggerInterface.loggerEngine.DEBUG("INIT CHUNK MAP " + saveName); LoggerInterface.loggerEngine.DEBUG("INIT CHUNK MAP " + saveName);
if(FileUtils.getSaveFile(saveName, "chunk.map").exists()){ if(FileUtils.getSaveFile(saveName, "chunk.map").exists()){
worldPosFileMap = FileUtils.loadObjectFromSavePath(saveName, "chunk.map", Map.class); rVal = FileUtils.loadObjectFromSavePath(saveName, "chunk.map", ChunkDiskMap.class);
LoggerInterface.loggerEngine.DEBUG("POS FILE MAP: " + worldPosFileMap.keySet()); LoggerInterface.loggerEngine.DEBUG("POS FILE MAP: " + rVal.worldPosFileMap.keySet());
} else { } else {
worldPosFileMap = new HashMap<String,String>(); rVal = new ChunkDiskMap();
} }
return rVal;
}
/**
* Initializes a diskmap based on a given save name
* @param saveName The save name
*/
public static ChunkDiskMap init(){
return new ChunkDiskMap();
} }
/** /**

View File

@ -106,7 +106,7 @@ public class ServerTerrainManager {
model = terrainGen.generateModel(); model = terrainGen.generateModel();
this.chunkGenerator.setModel(model); this.chunkGenerator.setModel(model);
model.setInterpolationRandomDampener(SERVER_TERRAIN_MANAGER_DAMPENER); model.setInterpolationRandomDampener(SERVER_TERRAIN_MANAGER_DAMPENER);
this.chunkDiskMap = new ChunkDiskMap(); this.chunkDiskMap = ChunkDiskMap.init();
} }
/** /**
@ -157,8 +157,7 @@ public class ServerTerrainManager {
model.setElevationArray(elevation); model.setElevationArray(elevation);
} }
//load chunk disk map //load chunk disk map
chunkDiskMap = new ChunkDiskMap(); chunkDiskMap = ChunkDiskMap.init(saveName);
chunkDiskMap.init(saveName);
} }
/** /**
@ -296,10 +295,6 @@ public class ServerTerrainManager {
*/ */
public void deformTerrainAtLocationToValue(Vector3i worldPos, Vector3i voxelPos, float weight, int value){ public void deformTerrainAtLocationToValue(Vector3i worldPos, Vector3i voxelPos, float weight, int value){
TerrainModification modification = new TerrainModification(worldPos,voxelPos,weight,value); TerrainModification modification = new TerrainModification(worldPos,voxelPos,weight,value);
//could be null if, for instance, arena mode
if(model != null){
model.addModification(modification);
}
if(chunkCache.containsChunk(worldPos.x,worldPos.y,worldPos.z,ChunkData.NO_STRIDE)){ if(chunkCache.containsChunk(worldPos.x,worldPos.y,worldPos.z,ChunkData.NO_STRIDE)){
ServerTerrainChunk chunk = chunkCache.get(worldPos.x,worldPos.y,worldPos.z, ChunkData.NO_STRIDE); ServerTerrainChunk chunk = chunkCache.get(worldPos.x,worldPos.y,worldPos.z, ChunkData.NO_STRIDE);
chunk.addModification(modification); chunk.addModification(modification);

View File

@ -1,21 +0,0 @@
package electrosphere.server.terrain.models;
import java.util.ArrayList;
import java.util.List;
/**
* Modifications made to terrain
*/
public class ModificationList {
List<TerrainModification> modifications = new ArrayList<TerrainModification>();
public List<TerrainModification> getModifications() {
return modifications;
}
public void addModification(TerrainModification modification){
modifications.add(modification);
}
}

View File

@ -1,8 +1,5 @@
package electrosphere.server.terrain.models; package electrosphere.server.terrain.models;
import java.util.HashMap;
import java.util.Map;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator; import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
@ -61,11 +58,6 @@ public class TerrainModel {
* The real coordinate ocean threshold * The real coordinate ocean threshold
*/ */
float realOceanThreshold; float realOceanThreshold;
/**
* The map of modifications applied to the model
*/
Map<String,ModificationList> modifications;
/** /**
* The seed of the terrain * The seed of the terrain
@ -84,7 +76,6 @@ public class TerrainModel {
* Private constructor * Private constructor
*/ */
TerrainModel() { TerrainModel() {
this.modifications = new HashMap<String,ModificationList>();
} }
/** /**
@ -108,7 +99,6 @@ public class TerrainModel {
this.elevation = elevation; this.elevation = elevation;
this.realMountainThreshold = realMountainThreshold; this.realMountainThreshold = realMountainThreshold;
this.realOceanThreshold = realOceanThreshold; this.realOceanThreshold = realOceanThreshold;
this.modifications = new HashMap<String,ModificationList>();
} }
/** /**
@ -458,55 +448,6 @@ public class TerrainModel {
public float getRealOceanThreshold() { public float getRealOceanThreshold() {
return realOceanThreshold; return realOceanThreshold;
} }
/**
* Gets a modification key
* @param x The world x position
* @param y The world y position
* @param z The world z position
* @return The key
*/
public String getModificationKey(int x, int y, int z){
return x + "_" + y + "_" + z;
}
/**
* Adds a terrain modification to the model
* @param modification The modification
*/
public void addModification(TerrainModification modification){
String key = getModificationKey(modification.getWorldPos().x,modification.getWorldPos().y,modification.getWorldPos().z);
ModificationList list;
if(!modifications.containsKey(key)){
list = new ModificationList();
modifications.put(key, list);
} else {
list = modifications.get(key);
}
list.addModification(modification);
}
/**
* Checks if a modification has been applied at a world position
* @param worldX The x coordinate of the world position
* @param worldY The y coordinate of the world position
* @param worldZ The z coordinate of the world position
* @return true if there is a modification, false otherwise
*/
public boolean containsModificationsAtCoord(int worldX, int worldY, int worldZ){
return modifications.containsKey(getModificationKey(worldX, worldY, worldZ));
}
/**
* Gets the terrain modification at the world position
* @param worldX The x coordinate of the world position
* @param worldY The y coordinate of the world position
* @param worldZ The z coordinate of the world position
* @return The modification if there is one at the position, null otherwise
*/
public ModificationList getModifications(int worldX, int worldY, int worldZ){
return modifications.get(getModificationKey(worldX, worldY, worldZ));
}
/** /**
* Sets the elevation array (For instance when read from save file on loading a save) * Sets the elevation array (For instance when read from save file on loading a save)

View File

@ -3,14 +3,37 @@ package electrosphere.server.terrain.models;
import org.joml.Vector3i; import org.joml.Vector3i;
/** /**
* A modification made to terrain * A modification made to a terrain chunk
*/ */
public class TerrainModification { public class TerrainModification {
/**
* The world position of the modification
*/
Vector3i worldPos; Vector3i worldPos;
/**
* The voxel position within the chunk that was modified
*/
Vector3i voxelPos; Vector3i voxelPos;
/**
* The new weight
*/
float weight; float weight;
/**
* The new type of voxel
*/
int value; int value;
/**
* Constructor
* @param worldPos The world position of the modification
* @param voxelPos The voxel position within the chunk that was modified
* @param weight The new weight
* @param value The new type of voxel
*/
public TerrainModification(Vector3i worldPos, Vector3i voxelPos, float weight, int value) { public TerrainModification(Vector3i worldPos, Vector3i voxelPos, float weight, int value) {
this.worldPos = worldPos; this.worldPos = worldPos;
this.voxelPos = voxelPos; this.voxelPos = voxelPos;
@ -18,18 +41,34 @@ public class TerrainModification {
this.value = value; this.value = value;
} }
/**
* Gets the world position of the modification
* @return The world position
*/
public Vector3i getWorldPos() { public Vector3i getWorldPos() {
return worldPos; return worldPos;
} }
/**
* Gets the new relative voxel position of the modification
* @return The relative voxel position
*/
public Vector3i getVoxelPos() { public Vector3i getVoxelPos() {
return voxelPos; return voxelPos;
} }
/**
* Gets the new weight
* @return The new weight
*/
public float getWeight(){ public float getWeight(){
return weight; return weight;
} }
/**
* Gets the new type of voxel
* @return The new type of voxel
*/
public int getValue() { public int getValue() {
return value; return value;
} }