terrain editing/saving work
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-04-15 21:55:54 -04:00
parent 01595f3228
commit ef067a0d34
8 changed files with 52 additions and 18 deletions

View File

@ -16,6 +16,6 @@
- Spawn player in a town with a quest to complete a nearby dungeon
+ bug fixes
Can't drop item out of inventory
- Terrain edits do not save
+ unreproducible bugs

View File

@ -1503,6 +1503,7 @@ Associate each server connection with a character ID
Code cleanup
Fix dig script function
Fix shovel functionality
Terrain editing/saving work

View File

@ -157,8 +157,7 @@ public class SaveUtils {
//write server structures
Globals.realmManager.save(saveName);
//close the server
Globals.server.close();
LoggerInterface.loggerEngine.WARNING("Finished saving " + saveName);
}
/**

View File

@ -146,9 +146,9 @@ public class ChunkDiskMap {
lock.lock();
LoggerInterface.loggerEngine.INFO("Load chunk " + worldX + " " + worldY + " " + worldZ);
ServerTerrainChunk rVal = null;
if(containsTerrainAtPosition(worldX, worldY, worldZ)){
if(this.containsTerrainAtPosition(worldX, worldY, worldZ)){
//read file
String fileName = worldPosFileMap.get(getTerrainChunkKey(worldX, worldY, worldZ));
String fileName = worldPosFileMap.get(ChunkDiskMap.getTerrainChunkKey(worldX, worldY, worldZ));
byte[] rawDataCompressed = FileUtils.loadBinaryFromSavePath(Globals.currentSave.getName(), "/terrain/" + fileName);
//decompress
byte[] rawData = null;
@ -209,7 +209,7 @@ public class ChunkDiskMap {
LoggerInterface.loggerEngine.DEBUG("Save to disk: " + terrainChunk.getWorldX() + " " + terrainChunk.getWorldY() + " " + terrainChunk.getWorldZ());
//get the file name for this chunk
String fileName = null;
String chunkKey = getTerrainChunkKey(terrainChunk.getWorldX(),terrainChunk.getWorldY(),terrainChunk.getWorldZ());
String chunkKey = ChunkDiskMap.getTerrainChunkKey(terrainChunk.getWorldX(),terrainChunk.getWorldY(),terrainChunk.getWorldZ());
if(worldPosFileMap.containsKey(chunkKey)){
fileName = worldPosFileMap.get(chunkKey);
} else {

View File

@ -12,7 +12,9 @@ import electrosphere.server.terrain.manager.ServerTerrainChunk;
*/
public class TerrainEditing {
//the minimum value before hard setting to 0
/**
* the minimum value before hard setting to 0
*/
static final float MINIMUM_FULL_VALUE = 0.01f;
/**
@ -120,13 +122,14 @@ public class TerrainEditing {
currentPositionMagnitude > 0 &&
(data = voxelCellManager.getChunkAtPosition(chunkPos)) != null
){
int typeAtPos = voxelCellManager.getVoxelTypeAtLocalPosition(chunkPos, voxelPos);
float current = data.getWeights()[voxelPos.x][voxelPos.y][voxelPos.z];
//hard clamp so it doesn't go over 1
float finalValue = Math.max(Math.min(current + weight / distance,1),-1);
if(finalValue < MINIMUM_FULL_VALUE && current > MINIMUM_FULL_VALUE){
if(finalValue < MINIMUM_FULL_VALUE && current >= MINIMUM_FULL_VALUE){
finalValue = -1;
typeAtPos = ServerTerrainChunk.VOXEL_TYPE_AIR;
}
int typeAtPos = voxelCellManager.getVoxelTypeAtLocalPosition(chunkPos, voxelPos);
voxelCellManager.editChunk(chunkPos, voxelPos, finalValue, typeAtPos);
}
}

View File

@ -9,6 +9,8 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import electrosphere.server.terrain.diskmap.ChunkDiskMap;
/**
* Caches chunk data on the server
*/
@ -64,11 +66,24 @@ public class ServerChunkCache {
*/
Semaphore lock = new Semaphore(1);
/**
* The disk map to use for file io
*/
ChunkDiskMap chunkDiskMap;
/**
* Constructor
* @param diskMap The disk map to use for file io
*/
public ServerChunkCache(ChunkDiskMap chunkDiskMap){
this.chunkDiskMap = chunkDiskMap;
}
/**
* Gets the collection of server terrain chunks that are cached
* @return The collection of chunks
*/
public Collection<ServerTerrainChunk> getContents(){
public Collection<ServerTerrainChunk> getFullRes(){
lock.acquireUninterruptibly();
Collection<ServerTerrainChunk> rVal = Collections.unmodifiableCollection(cacheMapFullRes.values());
lock.release();
@ -100,10 +115,11 @@ public class ServerChunkCache {
ServerTerrainChunk rVal = null;
Long key = this.getKey(worldX, worldY, worldZ);
lock.acquireUninterruptibly();
queryRecencyQueue.remove(key);
queryRecencyQueue.add(0, key);
Map<Long,ServerTerrainChunk> cache = this.getCache(stride);
rVal = cache.get(key);
if(queryRecencyQueue.remove(key)){
queryRecencyQueue.add(0, key);
Map<Long,ServerTerrainChunk> cache = this.getCache(stride);
rVal = cache.get(key);
}
lock.release();
return rVal;
}
@ -124,7 +140,10 @@ public class ServerChunkCache {
cache.put(key, chunk);
while(queryRecencyQueue.size() > cacheSize){
Long oldKey = queryRecencyQueue.remove(queryRecencyQueue.size() - 1);
cacheMapFullRes.remove(oldKey);
ServerTerrainChunk fullRes = cacheMapFullRes.remove(oldKey);
if(fullRes != null){
this.chunkDiskMap.saveToDisk(fullRes);
}
cacheMapHalfRes.remove(oldKey);
cacheMapQuarterRes.remove(oldKey);
cacheMapEighthRes.remove(oldKey);

View File

@ -27,6 +27,11 @@ public class ServerTerrainChunk {
*/
public static final int CHUNK_PLACEMENT_OFFSET = CHUNK_DATA_GENERATOR_SIZE - 1;
/**
* An empty terrain voxel
*/
public static final int VOXEL_TYPE_AIR = 0;
/**
* Gets the x coordinate of the world position of the chunk
*/

View File

@ -44,7 +44,9 @@ public class ServerTerrainManager {
*/
public static final int VERTICAL_INTERPOLATION_RATIO = 50;
//the interpolation width of a server terrain manager is hard coded at the moment to make sure it's divisible by the sub chunk calculations
/**
* the interpolation width of a server terrain manager is hard coded at the moment to make sure it's divisible by the sub chunk calculations
*/
public static final int SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO = 128;
/**
@ -67,7 +69,7 @@ public class ServerTerrainManager {
* The cache of chunks
*/
@Exclude
ServerChunkCache chunkCache = new ServerChunkCache();
ServerChunkCache chunkCache;
//The map of chunk position <-> file on disk containing chunk data
ChunkDiskMap chunkDiskMap = null;
@ -108,6 +110,7 @@ public class ServerTerrainManager {
generator.generate(this.model);
this.chunkGenerator.setModel(this.model);
this.chunkDiskMap = ChunkDiskMap.init();
this.chunkCache = new ServerChunkCache(this.chunkDiskMap);
}
/**
@ -123,6 +126,7 @@ public class ServerTerrainManager {
generator.generate(this.model);
this.chunkGenerator.setModel(this.model);
this.chunkDiskMap = ChunkDiskMap.init();
this.chunkCache = new ServerChunkCache(this.chunkDiskMap);
}
/**
@ -165,7 +169,7 @@ public class ServerTerrainManager {
FileUtils.saveBinaryToSavePath(saveName, "./biome.dat", shortBuff.array());
}
//for each chunk, save via disk map
for(ServerTerrainChunk chunk : this.chunkCache.getContents()){
for(ServerTerrainChunk chunk : this.chunkCache.getFullRes()){
chunkDiskMap.saveToDisk(chunk);
}
//save disk map itself
@ -219,6 +223,9 @@ public class ServerTerrainManager {
}
//load chunk disk map
chunkDiskMap = ChunkDiskMap.init(saveName);
//init cache
this.chunkCache = new ServerChunkCache(this.chunkDiskMap);
}
/**