more visibility into gridded cell manager
This commit is contained in:
parent
72e329d855
commit
7df05d611d
@ -1389,13 +1389,11 @@ Floating world origin
|
||||
- Separately simulated regions of physics that dynamically merge/unmerge based on chunk loading
|
||||
|
||||
Bug Fixes
|
||||
- Server not regenerating physics entities correctly after block edit
|
||||
- Fix hitbox placement does not scale with entity scale on server
|
||||
- Calculate bounding sphere for meshes by deforming vertices with bone default pose instead of no bone deform
|
||||
- Fix light cluster mapping for foliage shader
|
||||
- Fix flickering when applying yoga signal (may need to rethink arch here)
|
||||
- Fix virtual scrollables not working
|
||||
- Fix single blades of grass generating in bad locations
|
||||
|
||||
Startup Performance
|
||||
- Allow texture map to bind multiple model paths to a single set of mesh->textures
|
||||
|
||||
@ -8,7 +8,7 @@ import electrosphere.server.datacell.Realm;
|
||||
import imgui.ImGui;
|
||||
|
||||
/**
|
||||
*
|
||||
* Debug menu for gridded managers
|
||||
*/
|
||||
public class ImGuiGriddedManager {
|
||||
|
||||
@ -19,7 +19,7 @@ public class ImGuiGriddedManager {
|
||||
* Creates the windows in this file
|
||||
*/
|
||||
protected static void createGriddedManagerWindows(){
|
||||
createGriddedManagerWindow();
|
||||
ImGuiGriddedManager.createGriddedManagerWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,8 +38,14 @@ public class ImGuiGriddedManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(manager != null && manager.getLoadedCells() != null){
|
||||
ImGui.text("Loaded Cells: " + manager.getLoadedCells().size());
|
||||
if(manager != null){
|
||||
if(manager.getLoadedCells() != null){
|
||||
ImGui.text("Loaded Cells: " + manager.getLoadedCells().size());
|
||||
}
|
||||
if(manager.getCellPlayerlessFrameMap() != null){
|
||||
ImGui.text("Playerless tracking map size: " + manager.getCellPlayerlessFrameMap().keySet().size());
|
||||
}
|
||||
ImGui.text("Cells cleaned last frame: " + manager.getNumCleaned());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@ public class ServerContentManager {
|
||||
* @param cell The cell
|
||||
*/
|
||||
public void generateContentForDataCell(Realm realm, Vector3i worldPos, ServerDataCell cell, Long cellKey){
|
||||
Globals.profiler.beginCpuSample("ServerContentManager.generateContentForDataCell");
|
||||
String fullPath = "/content/" + cellKey + ".dat";
|
||||
if(generateContent){ //in other words, if not arena mode
|
||||
if(FileUtils.checkSavePathExists(Globals.currentSave.getName(), fullPath)){
|
||||
@ -68,6 +69,7 @@ public class ServerContentManager {
|
||||
// ),
|
||||
// Globals.navMeshManager.getBlockerCache().getBlocker(worldPos.x, worldPos.z))
|
||||
// );
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -130,6 +130,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* Map of world position key -> physics cell
|
||||
*/
|
||||
Map<Long,PhysicsDataCell> posPhysicsMap = new HashMap<Long,PhysicsDataCell>();
|
||||
|
||||
/**
|
||||
* Number of data cells cleaned up in the most recent frame
|
||||
*/
|
||||
int numCleaned = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -183,8 +188,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
|
||||
//create data cell
|
||||
this.createServerDataCell(targetPos);
|
||||
//add to loaded cells
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
||||
//add player
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
}
|
||||
@ -224,18 +227,16 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
for(int z = newPosition.x - playerSimulationRadius; z < newPosition.z + playerSimulationRadius + 1; z++){
|
||||
if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(new Vector3i(x, y, z), newPosition, playerSimulationRadius)){
|
||||
Vector3i targetPos = new Vector3i(x,y,z);
|
||||
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
||||
if(groundDataCells.get(this.getServerDataCellKey(targetPos)) != null){
|
||||
loadedCellsLock.lock();
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
groundDataCells.get(this.getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
loadedCellsLock.unlock();
|
||||
} else {
|
||||
loadedCellsLock.lock();
|
||||
//create data cell
|
||||
createServerDataCell(targetPos);
|
||||
//add to loaded cells
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(getServerDataCellKey(targetPos)),0);
|
||||
this.createServerDataCell(targetPos);
|
||||
//add player
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
groundDataCells.get(this.getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
loadedCellsLock.unlock();
|
||||
}
|
||||
}
|
||||
@ -327,6 +328,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @return True if the player changed cell, false otherwise
|
||||
*/
|
||||
public boolean updatePlayerPositions(){
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions");
|
||||
boolean playerChangedChunk = false;
|
||||
for(Player player : Globals.playerManager.getPlayers()){
|
||||
Entity playerEntity = player.getPlayerEntity();
|
||||
@ -342,6 +344,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
|
||||
//remove from cells that are out of range
|
||||
loadedCellsLock.lock();
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Remove from old cells");
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
Vector3i cellWorldPos = this.getCellWorldPosition(cell);
|
||||
if(cell.containsPlayer(player) && !this.shouldContainPlayer(cellWorldPos, newPosition, playerSimulationRadius)){
|
||||
@ -352,9 +355,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
this.broadcastDestructionToPlayer(player, cell);
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
loadedCellsLock.unlock();
|
||||
|
||||
//Add to cells that are in range
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Create new cells");
|
||||
for(int x = newPosition.x - playerSimulationRadius + 1; x < newPosition.x + playerSimulationRadius; x++){
|
||||
for(int y = newPosition.y - playerSimulationRadius + 1; y < newPosition.y + playerSimulationRadius; y++){
|
||||
for(int z = newPosition.z - playerSimulationRadius + 1; z < newPosition.z + playerSimulationRadius; z++){
|
||||
@ -371,8 +376,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
loadedCellsLock.lock();
|
||||
//create data cell
|
||||
this.createServerDataCell(targetPos);
|
||||
//add to loaded cells
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(targetPos)),0);
|
||||
//add player
|
||||
groundDataCells.get(this.getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
loadedCellsLock.unlock();
|
||||
@ -381,8 +384,10 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
}
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
return playerChangedChunk;
|
||||
}
|
||||
|
||||
@ -391,9 +396,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* Unloads all chunks that haven't had players in them for a set amount of time
|
||||
*/
|
||||
public void unloadPlayerlessChunks(){
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks");
|
||||
if(this.unloadCells){
|
||||
//TODO: improve to make have less performance impact
|
||||
loadedCellsLock.lock();
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Increment cleaning time");
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
if(cellPlayerlessFrameMap.containsKey(cell)){
|
||||
if(cell.isReady() && cell.getPlayers().size() < 1){
|
||||
@ -409,6 +416,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
}
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Deconstruct timed out cells");
|
||||
this.numCleaned = toCleanQueue.size();
|
||||
for(ServerDataCell cell : toCleanQueue){
|
||||
boolean containsPlayerEntity = false;
|
||||
//clear all entities in cell
|
||||
@ -433,24 +443,38 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
if(containsPlayerEntity){
|
||||
continue;
|
||||
}
|
||||
parent.deregisterCell(cell);
|
||||
Vector3i worldPos = getCellWorldPosition(cell);
|
||||
Long key = getServerDataCellKey(worldPos);
|
||||
groundDataCells.remove(key);
|
||||
this.posPhysicsMap.remove(key);
|
||||
this.cellPositionMap.remove(cell);
|
||||
this.cellPlayerlessFrameMap.remove(cell);
|
||||
Vector3i worldPos = this.getCellWorldPosition(cell);
|
||||
Long key = this.getServerDataCellKey(worldPos);
|
||||
|
||||
//offload all entities in cell to chunk file
|
||||
//entities are saved 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 - Destroy entities");
|
||||
serverContentManager.saveContentToDisk(key, cell.getScene().getEntityList());
|
||||
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 terrain");
|
||||
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.cellPlayerlessFrameMap.remove(cell);
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
loadedCellsLock.unlock();
|
||||
toCleanQueue.clear();
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -534,8 +558,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
loadedCellsLock.lock();
|
||||
//create data cell
|
||||
this.createServerDataCell(worldPos);
|
||||
//add to loaded cells
|
||||
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
||||
loadedCellsLock.unlock();
|
||||
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
||||
LoggerInterface.loggerEngine.ERROR(
|
||||
@ -574,20 +596,24 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
}
|
||||
|
||||
//queue fluid simulation
|
||||
Vector3i cellPos = this.getCellWorldPosition(cell);
|
||||
if(cellPos != null){
|
||||
this.serverFluidManager.queue(cellPos.x, cellPos.y, cellPos.z);
|
||||
if(Globals.RUN_FLUIDS){
|
||||
Vector3i cellPos = this.getCellWorldPosition(cell);
|
||||
if(cellPos != null){
|
||||
this.serverFluidManager.queue(cellPos.x, cellPos.y, cellPos.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//simulate fluids
|
||||
this.serverFluidManager.simulate((ServerFluidChunk fluidChunk) -> {
|
||||
ServerDataCell cell = getCellAtWorldPosition(fluidChunk.getWorldPosition());
|
||||
ServerFluidChunk chunk = getFluidChunkAtPosition(fluidChunk.getWorldPosition());
|
||||
cell.broadcastNetworkMessage(
|
||||
TerrainMessage.constructupdateFluidDataMessage(fluidChunk.getWorldX(), fluidChunk.getWorldY(), fluidChunk.getWorldZ(), TerrainProtocol.constructFluidByteBuffer(chunk).array())
|
||||
);
|
||||
});
|
||||
if(Globals.RUN_FLUIDS){
|
||||
this.serverFluidManager.simulate((ServerFluidChunk fluidChunk) -> {
|
||||
ServerDataCell cell = getCellAtWorldPosition(fluidChunk.getWorldPosition());
|
||||
ServerFluidChunk chunk = getFluidChunkAtPosition(fluidChunk.getWorldPosition());
|
||||
cell.broadcastNetworkMessage(
|
||||
TerrainMessage.constructupdateFluidDataMessage(fluidChunk.getWorldX(), fluidChunk.getWorldY(), fluidChunk.getWorldZ(), TerrainProtocol.constructFluidByteBuffer(chunk).array())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
loadedCellsLock.unlock();
|
||||
this.unloadPlayerlessChunks();
|
||||
@ -683,9 +709,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @param cell The cell itself
|
||||
*/
|
||||
private ServerDataCell createServerDataCell(Vector3i worldPos){
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.createServerDataCell");
|
||||
ServerDataCell rVal = parent.createNewCell();
|
||||
Long cellKey = this.getServerDataCellKey(worldPos);
|
||||
groundDataCells.put(cellKey,rVal);
|
||||
cellPlayerlessFrameMap.put(rVal,0);
|
||||
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
|
||||
cellPositionMap.put(rVal,new Vector3i(worldPos));
|
||||
serverContentManager.generateContentForDataCell(parent, worldPos, rVal, cellKey);
|
||||
@ -693,6 +721,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
Long key = this.getServerDataCellKey(worldPos);
|
||||
PhysicsDataCell cell = posPhysicsMap.get(key);
|
||||
GriddedDataCellManager.runPhysicsGenerationThread(worldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.parent);
|
||||
Globals.profiler.endCpuSample();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@ -858,14 +887,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
return returnPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of loaded cells
|
||||
* @return The set of loaded cells
|
||||
*/
|
||||
public Collection<ServerDataCell> getLoadedCells(){
|
||||
return Collections.unmodifiableCollection(this.groundDataCells.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the executor service
|
||||
*/
|
||||
@ -918,4 +939,28 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
terrainEditLock.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of loaded cells
|
||||
* @return The set of loaded cells
|
||||
*/
|
||||
public Collection<ServerDataCell> getLoadedCells(){
|
||||
return Collections.unmodifiableCollection(this.groundDataCells.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of cells cleaned in the most recent frame
|
||||
* @return The number of cells cleaned
|
||||
*/
|
||||
public int getNumCleaned(){
|
||||
return this.numCleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the playerless cell->frame count map
|
||||
* @return The playerless cell->frame count map
|
||||
*/
|
||||
public Map<ServerDataCell,Integer> getCellPlayerlessFrameMap(){
|
||||
return cellPlayerlessFrameMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -308,8 +308,8 @@ public class ServerTerrainManager {
|
||||
* @param position The position to save
|
||||
*/
|
||||
public void savePositionToDisk(Vector3i position){
|
||||
if(chunkDiskMap != null){
|
||||
chunkDiskMap.saveToDisk(getChunk(position.x, position.y, position.z));
|
||||
if(chunkDiskMap != null && chunkCache.containsChunk(position.x, position.y, position.z, ChunkData.NO_STRIDE)){
|
||||
chunkDiskMap.saveToDisk(this.getChunk(position.x, position.y, position.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user