Revert "gridded data cell improvements"
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This reverts commit da3ada73d0.
This commit is contained in:
austin 2025-05-25 13:44:53 -04:00
parent 03035aa1fb
commit cf9dceff42
3 changed files with 100 additions and 150 deletions

View File

@ -1988,8 +1988,6 @@ Performance improvements
- Reduce bones on LOD human model
Increase human move speed
LOD components re-attach physics
Memory improvements
- Rely on vector pool more

View File

@ -72,112 +72,112 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
/**
* The number of frames without players that must pass before a server data cell is unloaded
*/
private static final int UNLOAD_FRAME_THRESHOLD = 100;
static final int UNLOAD_FRAME_THRESHOLD = 100;
/**
* The distance at which simulation is queued
*/
private static final double SIMULATION_DISTANCE_CUTOFF = 5;
static final double SIMULATION_DISTANCE_CUTOFF = 5;
/**
* Big number used when scanning for a data cell to spawn a macro object within
*/
private static final double MACRO_SCANNING_BIG_NUMBER = 10000;
static final double MACRO_SCANNING_BIG_NUMBER = 10000;
/**
* Used for generating physics chunks
*/
private ExecutorService generationService = null;
ExecutorService generationService = null;
/**
* The service for loading data cells from disk
*/
private GriddedDataCellLoaderService loaderService;
GriddedDataCellLoaderService loaderService;
/**
* Tracks whether this manager has been flagged to unload cells or not
*/
private boolean unloadCells = true;
boolean unloadCells = true;
/**
* These are going to be the natural ground grid of data cells, but we're going to have more than this
*/
private Map<Long,ServerDataCell> groundDataCells = new HashMap<Long,ServerDataCell>();
Map<Long,ServerDataCell> groundDataCells = new HashMap<Long,ServerDataCell>();
/**
* Map of server cell to its world position
*/
private Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
Map<ServerDataCell,Vector3i> cellPositionMap = new HashMap<ServerDataCell,Vector3i>();
/**
* Map of server data cell to the number of frames said cell has had no players
*/
private Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
/**
* A map of ServerDataCell->GriddedDataCellTrackingData
*/
private Map<ServerDataCell,GriddedDataCellTrackingData> cellTrackingMap = new HashMap<ServerDataCell,GriddedDataCellTrackingData>();
Map<ServerDataCell,GriddedDataCellTrackingData> cellTrackingMap = new HashMap<ServerDataCell,GriddedDataCellTrackingData>();
/**
* Loaded cells
*/
private ReentrantLock loadedCellsLock = new ReentrantLock();
ReentrantLock loadedCellsLock = new ReentrantLock();
/**
* Parent realm
*/
private Realm parent;
Realm parent;
/**
* The world data of the parent
*/
private ServerWorldData serverWorldData;
ServerWorldData serverWorldData;
/**
* Manager for terrain for this particular cell manager
*/
private ServerTerrainManager serverTerrainManager;
ServerTerrainManager serverTerrainManager;
/**
* Manager for fluids for this particular cell manager
*/
private ServerFluidManager serverFluidManager;
ServerFluidManager serverFluidManager;
/**
* Lock for terrain editing
*/
private Semaphore terrainEditLock = new Semaphore(1);
Semaphore terrainEditLock = new Semaphore(1);
/**
* Manager for getting entities to fill in a cell
*/
private ServerContentManager serverContentManager;
ServerContentManager serverContentManager;
/**
* Used for cleaning server data cells no longer in use from the realm
*/
private Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
Set<ServerDataCell> toCleanQueue = new HashSet<ServerDataCell>();
/**
* Map of world position key -> physics cell
*/
private Map<Long,PhysicsDataCell> posPhysicsMap = new HashMap<Long,PhysicsDataCell>();
Map<Long,PhysicsDataCell> posPhysicsMap = new HashMap<Long,PhysicsDataCell>();
/**
* Number of data cells cleaned up in the most recent frame
*/
private int numCleaned = 0;
int numCleaned = 0;
/**
* Queue of cells that need to have their physics regenerated (ie on block edits)
*/
private Map<Long,Vector3i> physicsQueue = new HashMap<Long,Vector3i>();
Map<Long,Vector3i> physicsQueue = new HashMap<Long,Vector3i>();
/**
* The pathfinder for the manager
*/
private VoxelPathfinder pathfinder;
VoxelPathfinder pathfinder;
/**
* Caches lookups for nearby entities between simulate() calls
@ -359,7 +359,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
loadedCellsLock.lock();
if(posPhysicsMap.containsKey(key)){
PhysicsDataCell cell = posPhysicsMap.get(key);
cell.destroyEntities();
cell.retireCell();
}
loadedCellsLock.unlock();
//get data to generate with
@ -384,7 +384,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
//the server will not be able to synchronize it properly.
ServerEntityUtils.initiallyPositionEntity(parent,blockEntity,realPos);
ServerEntityUtils.initiallyPositionEntity(parent,terrainEntity,realPos);
PhysicsDataCell cell = PhysicsDataCell.createPhysicsCell(terrainEntity, blockEntity);
PhysicsDataCell cell = PhysicsDataCell.createPhysicsCell(worldPos, terrainEntity, blockEntity);
cell.setTerrainChunk(terrainChunk);
cell.setBlockChunk(blockChunkData);
cell.generatePhysics();
@ -545,8 +545,39 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
continue;
}
this.unloadCell(cell);
Vector3i worldPos = this.getCellWorldPosition(cell);
Long key = this.getServerDataCellKey(worldPos);
//entities are serialized before tracking is removed. This makes sure that any side effects from calling destroyEntity (ie if it looks up the chunk that we're deleting)
//don't trigger the chunk to be re-created
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Serialize entities");
ContentSerialization serializedEntities = ContentSerialization.constructContentSerialization(cell.getScene().getEntityList());
Globals.profiler.endCpuSample();
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Destroy entities");
for(Entity entity : cell.getScene().getEntityList()){
ServerEntityUtils.destroyEntity(entity);
}
Globals.profiler.endCpuSample();
//save terrain to disk
//terrain is saved before tracking is removed. This makes sure that any side effects from calling savePositionToDisk (ie if it looks up the chunk that we're deleting)
//don't trigger the chunk to be re-created
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data");
this.loaderService.queueLocationBasedOperation(key, () -> {
serverContentManager.saveSerializationToDisk(key, serializedEntities);
serverTerrainManager.savePositionToDisk(worldPos);
});
Globals.profiler.endCpuSample();
//deregister from all tracking structures
parent.deregisterCell(cell);
groundDataCells.remove(key);
this.posPhysicsMap.remove(key);
this.cellPositionMap.remove(cell);
this.cellTrackingMap.remove(cell);
this.cellPlayerlessFrameMap.remove(cell);
}
Globals.profiler.endCpuSample();
loadedCellsLock.unlock();
@ -567,55 +598,26 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
toCleanQueue.add(cell);
}
for(ServerDataCell cell : toCleanQueue){
this.unloadCell(cell);
parent.deregisterCell(cell);
Vector3i worldPos = this.getCellWorldPosition(cell);
Long key = getServerDataCellKey(worldPos);
groundDataCells.remove(key);
this.posPhysicsMap.remove(key);
this.cellPositionMap.remove(cell);
this.cellPlayerlessFrameMap.remove(cell);
this.cellTrackingMap.remove(cell);
//offload all entities in cell to chunk file
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
//clear all entities in cell
for(Entity entity : cell.getScene().getEntityList()){
ServerEntityUtils.destroyEntity(entity);
}
}
loadedCellsLock.unlock();
this.serverTerrainManager.evictAll();
toCleanQueue.clear();
}
/**
* Unloads a server data cell
* @param cell The cell
*/
public void unloadCell(ServerDataCell cell){
Vector3i worldPos = this.getCellWorldPosition(cell);
Long key = this.getServerDataCellKey(worldPos);
//entities are serialized before tracking is removed. This makes sure that any side effects from calling destroyEntity (ie if it looks up the chunk that we're deleting)
//don't trigger the chunk to be re-created
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Serialize entities");
ContentSerialization serializedEntities = ContentSerialization.constructContentSerialization(cell.getScene().getEntityList());
Globals.profiler.endCpuSample();
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Destroy entities");
for(Entity entity : cell.getScene().getEntityList()){
ServerEntityUtils.destroyEntity(entity);
}
Globals.profiler.endCpuSample();
//save terrain to disk
//terrain is saved before tracking is removed. This makes sure that any side effects from calling savePositionToDisk (ie if it looks up the chunk that we're deleting)
//don't trigger the chunk to be re-created
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data");
this.loaderService.queueLocationBasedOperation(key, () -> {
serverContentManager.saveSerializationToDisk(key, serializedEntities);
serverTerrainManager.savePositionToDisk(worldPos);
});
Globals.profiler.endCpuSample();
//deregister from all tracking structures
this.parent.deregisterCell(cell);
this.groundDataCells.remove(key);
PhysicsDataCell releasedCell = this.posPhysicsMap.remove(key);
if(releasedCell != null){
releasedCell.destroyEntities();
}
this.cellPositionMap.remove(cell);
this.cellTrackingMap.remove(cell);
this.cellPlayerlessFrameMap.remove(cell);
}
/**
* Get data cell at a given real point in this realm
* @param point The real point
@ -817,7 +819,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
ServerEntityUtils.initiallyPositionEntity(realm,blockEntity,realPos);
ServerEntityUtils.initiallyPositionEntity(realm,terrainEntity,realPos);
PhysicsDataCell targetCell = PhysicsDataCell.createPhysicsCell(terrainEntity, blockEntity);
PhysicsDataCell targetCell = PhysicsDataCell.createPhysicsCell(worldPos, terrainEntity, blockEntity);
if(cell == null){
posPhysicsMap.put(key, targetCell);
} else {
@ -845,7 +847,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
//create physics entities
if(cell != null){
cell.destroyEntities();
cell.retireCell();
cell.generatePhysics();
} else {
targetCell.generatePhysics();
@ -880,9 +882,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
Long cellKey = this.getServerDataCellKey(localWorldPos);
loadedCellsLock.lock();
if(groundDataCells.containsKey(cellKey)){
throw new Error("Creating server data cell at position that already has a cell! " + localWorldPos);
}
groundDataCells.put(cellKey,rVal);
cellPlayerlessFrameMap.put(rVal,0);
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
@ -1155,21 +1154,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
return cellPlayerlessFrameMap;
}
/**
* Gets the tracking data for a cell
* @param cell The cell
* @return The tracking data as a string
*/
public String getCellData(ServerDataCell cell){
String message = "Failed to find position of cell!\n" +
"groundDataCells: " + this.groundDataCells.values().contains(cell) + "\n" +
"cellPositionMap: " + this.cellPositionMap.keySet().contains(cell) + "\n" +
"cellPlayerlessFrameMap: " + this.cellPositionMap.keySet().contains(cell) + "\n" +
"cellTrackingMap: " + this.cellTrackingMap.keySet().contains(cell) + "\n" +
"";
return message;
}
@Override
public List<Vector3d> findPath(Vector3d start, Vector3d end){
Vector3i startChunkPos = ServerWorldData.convertRealToChunkSpace(start);

View File

@ -3,6 +3,7 @@ package electrosphere.server.datacell.physics;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.terrain.data.TerrainChunkData;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.ServerEntityUtils;
@ -10,54 +11,39 @@ import electrosphere.entity.types.terrain.BlockChunkEntity;
import electrosphere.entity.types.terrain.TerrainChunk;
import electrosphere.renderer.meshgen.BlockMeshgen;
import electrosphere.renderer.meshgen.BlockMeshgen.BlockMeshData;
import electrosphere.server.datacell.Realm;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
import org.joml.Vector3i;
import org.ode4j.ode.DBody;
/**
* An entity which contains physics for terrain for a given chunk on the server
*/
public class PhysicsDataCell {
Vector3i worldPos;
/**
* The terrain physics entity
*/
private Entity physicsEntity;
Entity physicsEntity;
Entity blockPhysicsEntity;
/**
* The block physics entity
*/
private Entity blockPhysicsEntity;
ServerTerrainChunk terrainChunk;
BlockChunkData blockChunk;
DBody physicsObject;
/**
* The terrain chunk data
*/
private ServerTerrainChunk terrainChunk;
/**
* The block chunk data
*/
private BlockChunkData blockChunk;
/**
* The weight data
*/
private float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
/**
* The type data
*/
private int[][][] types = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
int[][][] types = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
/**
* The terrain vertex data
*/
private TerrainChunkData terrainChunkData;
TerrainChunkData terrainChunkData;
/**
* The block vertex data
*/
private BlockMeshData blockData;
BlockMeshData blockData;
/**
* Creates a physics cell
@ -66,6 +52,7 @@ public class PhysicsDataCell {
* @return The cell
*/
public static PhysicsDataCell createPhysicsCell(
Vector3i worldPos,
Entity physicsEntity,
Entity blockPhysicsEntity
@ -73,47 +60,19 @@ public class PhysicsDataCell {
PhysicsDataCell rVal = new PhysicsDataCell();
rVal.physicsEntity = physicsEntity;
rVal.blockPhysicsEntity = blockPhysicsEntity;
rVal.worldPos = worldPos;
return rVal;
}
/**
* Retires a physics data cell
*/
public void destroyEntities(){
public void retireCell(){
ServerEntityUtils.destroyEntity(physicsEntity);
this.physicsEntity = null;
ServerEntityUtils.destroyEntity(blockPhysicsEntity);
this.blockPhysicsEntity = null;
}
/**
* Frees the data in this cell
*/
public void free(){
this.destroyEntities();
}
/**
* Resets the state of the physics data cell
*/
public void reset(
Vector3i worldPos,
Entity physicsEntity,
Entity blockPhysicsEntity
){
if(this.physicsEntity != null){
ServerEntityUtils.destroyEntity(this.physicsEntity);
}
if(this.blockPhysicsEntity != null){
ServerEntityUtils.destroyEntity(this.blockPhysicsEntity);
}
this.physicsEntity = physicsEntity;
this.blockPhysicsEntity = blockPhysicsEntity;
this.terrainChunk = null;
this.blockChunk = null;
this.terrainChunkData = null;
this.blockData = null;
}
/**
* Generates the physics entity for this chunk
@ -146,6 +105,15 @@ public class PhysicsDataCell {
localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
localBlockPhysicsEntity.putData(EntityDataStrings.BLOCK_ENTITY, true);
}
/**
* Destroys the physics for this data cell
*/
public void destroyPhysics(){
Realm realm = Globals.serverState.realmManager.getEntityRealm(physicsEntity);
realm.getCollisionEngine().destroyPhysics(physicsEntity);
realm.getCollisionEngine().destroyPhysics(blockPhysicsEntity);
}
/**
* Fills in the internal arrays of data for generate terrain models