GriddedDataCellTrackingData + reduce allocs
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
86344ebfeb
commit
86c867fe31
@ -1432,6 +1432,11 @@ Fix PoseActor position/rotation caching bug
|
||||
Bush drops sticks
|
||||
Unarmed combat
|
||||
|
||||
(04/04/2025)
|
||||
GriddedDataCellTrackingData created
|
||||
Reduce allocations in GriddedDataCellManager methods that loop cells
|
||||
Implement max distance for queueing for simulation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -28,17 +28,25 @@ import java.util.Set;
|
||||
*/
|
||||
public class ServerDataCell {
|
||||
|
||||
//all players attached to this server data cell
|
||||
/**
|
||||
* All players attached to this server data cell
|
||||
*/
|
||||
Set<Player> activePlayers = new HashSet<Player>();
|
||||
|
||||
//the navmesh for the data cell
|
||||
/**
|
||||
* The navmesh for the data cell
|
||||
*/
|
||||
NavMesh navMesh;
|
||||
|
||||
//the scene backing the server data cell
|
||||
/**
|
||||
* The scene backing the server data cell
|
||||
*/
|
||||
Scene scene;
|
||||
|
||||
//controls whether the server data cell simulates its entities or not
|
||||
boolean ready = false;
|
||||
/**
|
||||
* Controls whether the server data cell simulates its entities or not
|
||||
*/
|
||||
boolean ready = false;
|
||||
|
||||
/**
|
||||
* Constructs a datacell based on a virtual cell. Should be used when a player
|
||||
@ -50,6 +58,11 @@ public class ServerDataCell {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a server data cell
|
||||
* @param scene The scene to wrap the server data cell around
|
||||
* @return The server data cell
|
||||
*/
|
||||
protected static ServerDataCell createServerDataCell(Scene scene){
|
||||
return new ServerDataCell(scene);
|
||||
}
|
||||
@ -120,10 +133,10 @@ public class ServerDataCell {
|
||||
for(Player player : this.activePlayers){
|
||||
if(previousCell != null){
|
||||
if(!previousCell.containsPlayer(player)){
|
||||
serializeEntityToPlayer(creature,player);
|
||||
this.serializeEntityToPlayer(creature,player);
|
||||
}
|
||||
} else {
|
||||
serializeEntityToPlayer(creature,player);
|
||||
this.serializeEntityToPlayer(creature,player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,7 +156,7 @@ public class ServerDataCell {
|
||||
* @param entity The entity to serialize
|
||||
* @param player The player to send the entity to
|
||||
*/
|
||||
void serializeEntityToPlayer(Entity entity, Player player){
|
||||
private void serializeEntityToPlayer(Entity entity, Player player){
|
||||
if(!player.hasSentPlayerEntity() || player.getPlayerEntity() == null || player.getPlayerEntity() != entity){
|
||||
EntityType type = CommonEntityUtils.getEntityType(entity);
|
||||
if(type != null){
|
||||
|
||||
@ -64,6 +64,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
*/
|
||||
static final int UNLOAD_FRAME_THRESHOLD = 100;
|
||||
|
||||
/**
|
||||
* The distance at which simulation is queued
|
||||
*/
|
||||
static final double SIMULATION_DISTANCE_CUTOFF = 5;
|
||||
|
||||
/**
|
||||
* Used for generating physics chunks
|
||||
*/
|
||||
@ -89,6 +94,11 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
*/
|
||||
Map<ServerDataCell,Integer> cellPlayerlessFrameMap = new HashMap<ServerDataCell,Integer>();
|
||||
|
||||
/**
|
||||
* A map of ServerDataCell->GriddedDataCellTrackingData
|
||||
*/
|
||||
Map<ServerDataCell,GriddedDataCellTrackingData> cellTrackingMap = new HashMap<ServerDataCell,GriddedDataCellTrackingData>();
|
||||
|
||||
/**
|
||||
* Loaded cells
|
||||
*/
|
||||
@ -178,21 +188,23 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
Globals.realmManager.setPlayerRealm(player, parent);
|
||||
int playerSimulationRadius = player.getSimulationRadius();
|
||||
Vector3i worldPos = player.getWorldPos();
|
||||
Vector3i tempVec = new Vector3i();
|
||||
for(int x = worldPos.x - playerSimulationRadius; x < worldPos.x + playerSimulationRadius + 1; x++){
|
||||
for(int y = worldPos.y - playerSimulationRadius; y < worldPos.y + playerSimulationRadius + 1; y++){
|
||||
for(int z = worldPos.z - playerSimulationRadius; z < worldPos.z + playerSimulationRadius + 1; z++){
|
||||
if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(new Vector3i(x,y,z), worldPos, playerSimulationRadius)){
|
||||
Vector3i targetPos = new Vector3i(x,y,z);
|
||||
tempVec.set(x,y,z);
|
||||
double distance = this.calcDistance(tempVec, worldPos);
|
||||
if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(distance, playerSimulationRadius)){
|
||||
LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
|
||||
loadedCellsLock.lock();
|
||||
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
if(groundDataCells.get(this.getServerDataCellKey(tempVec)) != null){
|
||||
groundDataCells.get(this.getServerDataCellKey(tempVec)).addPlayer(player);
|
||||
} else {
|
||||
LoggerInterface.loggerEngine.DEBUG("Creating new cell @ " + x + " " + y + " " + z);
|
||||
//create data cell
|
||||
this.createServerDataCell(targetPos);
|
||||
this.createServerDataCell(tempVec);
|
||||
//add player
|
||||
groundDataCells.get(getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
groundDataCells.get(this.getServerDataCellKey(tempVec)).addPlayer(player);
|
||||
}
|
||||
loadedCellsLock.unlock();
|
||||
}
|
||||
@ -211,7 +223,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
player.setWorldPos(newPosition);
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
Vector3i worldPos = this.getCellWorldPosition(cell);
|
||||
if(cell.containsPlayer(player) && !this.shouldContainPlayer(worldPos, newPosition, playerSimulationRadius)){
|
||||
if(cell.containsPlayer(player) && !this.shouldContainPlayer(this.calcDistance(worldPos, newPosition), playerSimulationRadius)){
|
||||
cell.removePlayer(player);
|
||||
this.broadcastDestructionToPlayer(player, cell);
|
||||
if(cell.getScene().containsEntity(player.getPlayerEntity())){
|
||||
@ -228,7 +240,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
for(int x = newPosition.x - playerSimulationRadius; x < newPosition.x + playerSimulationRadius + 1; x++){
|
||||
for(int y = newPosition.y - playerSimulationRadius; y < newPosition.y + playerSimulationRadius + 1; y++){
|
||||
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)){
|
||||
if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(this.calcDistance(new Vector3i(x, y, z), newPosition), playerSimulationRadius)){
|
||||
Vector3i targetPos = new Vector3i(x,y,z);
|
||||
if(groundDataCells.get(this.getServerDataCellKey(targetPos)) != null){
|
||||
loadedCellsLock.lock();
|
||||
@ -255,8 +267,18 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @param simRadius The simulation radius of the player
|
||||
* @return true if the player should be contained in the cell, false otherwise
|
||||
*/
|
||||
private boolean shouldContainPlayer(Vector3i cellWorldPos, Vector3i playerPos, int simRadius){
|
||||
return cellWorldPos.distance(playerPos) < simRadius;
|
||||
private boolean shouldContainPlayer(double distance, int simRadius){
|
||||
return distance < simRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance from the player to the cell
|
||||
* @param playerPos The player
|
||||
* @param cellWorldPos The cell
|
||||
* @return The distance
|
||||
*/
|
||||
public double calcDistance(Vector3i playerPos, Vector3i cellWorldPos){
|
||||
return cellWorldPos.distance(playerPos);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,7 +359,17 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @return True if the player changed cell, false otherwise
|
||||
*/
|
||||
public boolean updatePlayerPositions(){
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions");
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Reset chunk distances");
|
||||
loadedCellsLock.lock();
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Remove from old cells");
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
GriddedDataCellTrackingData trackingData = this.cellTrackingMap.get(cell);
|
||||
trackingData.setClosestPlayer(GriddedDataCellTrackingData.REALLY_LARGE_DISTANCE);
|
||||
}
|
||||
loadedCellsLock.unlock();
|
||||
Globals.profiler.endCpuSample();
|
||||
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Actually update player positions");
|
||||
boolean playerChangedChunk = false;
|
||||
for(Player player : Globals.playerManager.getPlayers()){
|
||||
Entity playerEntity = player.getPlayerEntity();
|
||||
@ -355,8 +387,13 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
loadedCellsLock.lock();
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Remove from old cells");
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
GriddedDataCellTrackingData trackingData = this.cellTrackingMap.get(cell);
|
||||
Vector3i cellWorldPos = this.getCellWorldPosition(cell);
|
||||
if(cell.containsPlayer(player) && !this.shouldContainPlayer(cellWorldPos, newPosition, playerSimulationRadius)){
|
||||
double distance = this.calcDistance(cellWorldPos, newPosition);
|
||||
if(distance < trackingData.getClosestPlayer()){
|
||||
trackingData.setClosestPlayer(distance);
|
||||
}
|
||||
if(cell.containsPlayer(player) && !this.shouldContainPlayer(distance, playerSimulationRadius)){
|
||||
if(cell.getScene().containsEntity(player.getPlayerEntity())){
|
||||
throw new Error("Trying to remove player from a cell that contains its entity!");
|
||||
}
|
||||
@ -369,14 +406,16 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
|
||||
//Add to cells that are in range
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.updatePlayerPositions - Create new cells");
|
||||
Vector3i tempVec = new Vector3i();
|
||||
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++){
|
||||
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(this.getServerDataCellKey(targetPos)) != null){
|
||||
tempVec.set(x,y,z);
|
||||
double distance = this.calcDistance(tempVec, newPosition);
|
||||
if(this.canCreateCell(x,y,z) && this.shouldContainPlayer(distance, playerSimulationRadius)){
|
||||
if(groundDataCells.get(this.getServerDataCellKey(tempVec)) != null){
|
||||
loadedCellsLock.lock();
|
||||
ServerDataCell cell = groundDataCells.get(this.getServerDataCellKey(targetPos));
|
||||
ServerDataCell cell = groundDataCells.get(this.getServerDataCellKey(tempVec));
|
||||
if(!cell.containsPlayer(player)){
|
||||
cell.addPlayer(player);
|
||||
}
|
||||
@ -384,9 +423,9 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
} else {
|
||||
loadedCellsLock.lock();
|
||||
//create data cell
|
||||
this.createServerDataCell(targetPos);
|
||||
this.createServerDataCell(tempVec);
|
||||
//add player
|
||||
groundDataCells.get(this.getServerDataCellKey(targetPos)).addPlayer(player);
|
||||
groundDataCells.get(this.getServerDataCellKey(tempVec)).addPlayer(player);
|
||||
loadedCellsLock.unlock();
|
||||
}
|
||||
}
|
||||
@ -484,6 +523,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
groundDataCells.remove(key);
|
||||
this.posPhysicsMap.remove(key);
|
||||
this.cellPositionMap.remove(cell);
|
||||
this.cellTrackingMap.remove(cell);
|
||||
this.cellPlayerlessFrameMap.remove(cell);
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
@ -506,12 +546,13 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
}
|
||||
for(ServerDataCell cell : toCleanQueue){
|
||||
parent.deregisterCell(cell);
|
||||
Vector3i worldPos = getCellWorldPosition(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
|
||||
@ -644,7 +685,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
* @return true if it should be simulated, false otherwise
|
||||
*/
|
||||
private boolean shouldSimulate(ServerDataCell cell){
|
||||
return cell.getPlayers().size() > 0;
|
||||
GriddedDataCellTrackingData trackingData = this.cellTrackingMap.get(cell);
|
||||
return cell.getPlayers().size() > 0 && trackingData.getClosestPlayer() < SIMULATION_DISTANCE_CUTOFF;
|
||||
}
|
||||
|
||||
|
||||
@ -739,24 +781,27 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
private ServerDataCell createServerDataCell(Vector3i worldPos){
|
||||
Globals.profiler.beginCpuSample("GriddedDataCellManager.createServerDataCell");
|
||||
ServerDataCell rVal = parent.createNewCell();
|
||||
Long cellKey = this.getServerDataCellKey(worldPos);
|
||||
Vector3i localWorldPos = new Vector3i(worldPos);
|
||||
Long cellKey = this.getServerDataCellKey(localWorldPos);
|
||||
|
||||
loadedCellsLock.lock();
|
||||
groundDataCells.put(cellKey,rVal);
|
||||
cellPlayerlessFrameMap.put(rVal,0);
|
||||
LoggerInterface.loggerEngine.DEBUG("Create server data cell with key " + cellKey);
|
||||
cellPositionMap.put(rVal,new Vector3i(worldPos));
|
||||
cellPositionMap.put(rVal,localWorldPos);
|
||||
GriddedDataCellTrackingData trackingData = new GriddedDataCellTrackingData();
|
||||
this.cellTrackingMap.put(rVal,trackingData);
|
||||
loadedCellsLock.unlock();
|
||||
|
||||
Long key = this.getServerDataCellKey(worldPos);
|
||||
Long key = this.getServerDataCellKey(localWorldPos);
|
||||
//generate content
|
||||
GriddedDataCellLoaderService.queueLocationBasedOperation(key, () -> {
|
||||
serverContentManager.generateContentForDataCell(parent, worldPos, rVal, cellKey);
|
||||
serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey);
|
||||
});
|
||||
//generates physics for the cell in a dedicated thread then finally registers
|
||||
loadedCellsLock.lock();
|
||||
PhysicsDataCell cell = posPhysicsMap.get(key);
|
||||
GriddedDataCellManager.runPhysicsGenerationThread(worldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.parent);
|
||||
GriddedDataCellManager.runPhysicsGenerationThread(localWorldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.parent);
|
||||
loadedCellsLock.unlock();
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
package electrosphere.server.datacell.gridded;
|
||||
|
||||
/**
|
||||
* Data associated with a ServerDataCell by the GriddedDataCellManager
|
||||
*/
|
||||
public class GriddedDataCellTrackingData {
|
||||
|
||||
/**
|
||||
* A really large distance used to reset the position
|
||||
*/
|
||||
public static final double REALLY_LARGE_DISTANCE = 1000;
|
||||
|
||||
/**
|
||||
* The from the cell to the closest player
|
||||
*/
|
||||
double closestPlayer;
|
||||
|
||||
/**
|
||||
* Gets the distance from the cell to the closest player
|
||||
* @return The distance
|
||||
*/
|
||||
public double getClosestPlayer() {
|
||||
return closestPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the distance to the closest player
|
||||
* @param closestPlayer The distance to the closest player
|
||||
*/
|
||||
public void setClosestPlayer(double closestPlayer) {
|
||||
this.closestPlayer = closestPlayer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user