From cf9dceff42111d451c60e3da2658421fdccf2d86 Mon Sep 17 00:00:00 2001 From: austin Date: Sun, 25 May 2025 13:44:53 -0400 Subject: [PATCH] Revert "gridded data cell improvements" This reverts commit da3ada73d0e54ac7f73ab9ff08d4f81f0497ee5d. --- docs/src/progress/renderertodo.md | 2 - .../gridded/GriddedDataCellManager.java | 162 ++++++++---------- .../datacell/physics/PhysicsDataCell.java | 86 +++------- 3 files changed, 100 insertions(+), 150 deletions(-) diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 8fe46679..873598be 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -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 diff --git a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java index 2157a25b..c06d1151 100644 --- a/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/gridded/GriddedDataCellManager.java @@ -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 groundDataCells = new HashMap(); + Map groundDataCells = new HashMap(); /** * Map of server cell to its world position */ - private Map cellPositionMap = new HashMap(); + Map cellPositionMap = new HashMap(); /** * Map of server data cell to the number of frames said cell has had no players */ - private Map cellPlayerlessFrameMap = new HashMap(); + Map cellPlayerlessFrameMap = new HashMap(); /** * A map of ServerDataCell->GriddedDataCellTrackingData */ - private Map cellTrackingMap = new HashMap(); + Map cellTrackingMap = new HashMap(); /** * 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 toCleanQueue = new HashSet(); + Set toCleanQueue = new HashSet(); /** * Map of world position key -> physics cell */ - private Map posPhysicsMap = new HashMap(); + Map posPhysicsMap = new HashMap(); /** * 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 physicsQueue = new HashMap(); + Map physicsQueue = new HashMap(); /** * 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 findPath(Vector3d start, Vector3d end){ Vector3i startChunkPos = ServerWorldData.convertRealToChunkSpace(start); diff --git a/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java b/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java index 96f133c9..d5d3432c 100644 --- a/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java +++ b/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java @@ -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