fixing up gridded data cell manager
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2024-11-13 21:08:32 -05:00
parent 755db7ba72
commit 9a20a64d5b
14 changed files with 205 additions and 82 deletions

View File

@ -1016,6 +1016,10 @@ Ability to replacing a player's entity
Fix shadows on main shader Fix shadows on main shader
Button to swap between player entity and editor entity Button to swap between player entity and editor entity
Fix physics being disabled on editing a level Fix physics being disabled on editing a level
Fix entity repositioning bugs + Enable recursive logic
Fix hitbox manager handling of destruction
Fix gridded data cell manager player + entity position handling and refactor to simplify logic
Add debug options for entities to reposition on server

View File

@ -0,0 +1,33 @@
package electrosphere.client.ui.menu.debug.entity;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import imgui.ImGui;
/**
* An entire tab of debug actions
*/
public class ImGuiEntityDebugActions {
/**
* Debug actions view
*/
protected static void drawDebugActions(boolean show, Entity detailViewEntity){
if(show && ImGui.collapsingHeader("Debug Actions")){
ImGui.indent();
if(detailViewEntity != null){
if(ImGui.button("Teleport to player")){
if(Globals.clientSceneWrapper.containsServerId(detailViewEntity.getId())){
ServerEntityUtils.repositionEntity(detailViewEntity, EntityUtils.getPosition(Globals.playerEntity));
}
}
}
ImGui.unindent();
}
}
}

View File

@ -63,6 +63,7 @@ public class ImGuiEntityMacros {
private static boolean showLinkedEntitiesTab = false;//show linked entities private static boolean showLinkedEntitiesTab = false;//show linked entities
private static boolean showServerViewDirTab = false; //show server view dir private static boolean showServerViewDirTab = false; //show server view dir
private static boolean showPhysicsTab = false; //show physics values private static boolean showPhysicsTab = false; //show physics values
private static boolean showDebugActionsTab = false; //show debug actions
/** /**
* Creates the windows in this file * Creates the windows in this file
@ -164,6 +165,9 @@ public class ImGuiEntityMacros {
if(HitboxCollectionState.hasHitboxState(detailViewEntity) && ImGui.checkbox("Hitbox State", showHitboxTab)){ if(HitboxCollectionState.hasHitboxState(detailViewEntity) && ImGui.checkbox("Hitbox State", showHitboxTab)){
showHitboxTab = !showHitboxTab; showHitboxTab = !showHitboxTab;
} }
if(ImGui.checkbox("Debug Actions", showDebugActionsTab)){
showDebugActionsTab = !showDebugActionsTab;
}
ImGui.treePop(); ImGui.treePop();
} }
ImGui.nextColumn(); ImGui.nextColumn();
@ -176,6 +180,7 @@ public class ImGuiEntityMacros {
ImGuiEntityMacros.drawLinkedEntities(); ImGuiEntityMacros.drawLinkedEntities();
ImGuiEntityMacros.drawServerViewDir(); ImGuiEntityMacros.drawServerViewDir();
ImGuiEntityMacros.drawPhysicsDetails(); ImGuiEntityMacros.drawPhysicsDetails();
ImGuiEntityDebugActions.drawDebugActions(showDebugActionsTab, detailViewEntity);
ImGuiEntityMacros.drawDataView(); ImGuiEntityMacros.drawDataView();
} }
}); });

View File

@ -84,6 +84,11 @@ public class CollisionEngine {
* This keeps the physics simulation much more stable than it would be otherwise. * This keeps the physics simulation much more stable than it would be otherwise.
*/ */
public static final int PHYSICS_SIMULATION_RESOLUTION = 5; public static final int PHYSICS_SIMULATION_RESOLUTION = 5;
/**
* Threshold after which the engine warns about collidable count
*/
public static final int COLLIDABLE_COUNT_WARNING_THRESHOLD = 1000;
//world data that the collision engine leverages for position correction and the like //world data that the collision engine leverages for position correction and the like
CollisionWorldData collisionWorldData; CollisionWorldData collisionWorldData;
@ -577,9 +582,14 @@ public class CollisionEngine {
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }
/**
* Registers a collision object with the server
* @param body The body
* @param collidable The corresponding collidable
*/
public void registerCollisionObject(DBody body, Collidable collidable){ public void registerCollisionObject(DBody body, Collidable collidable){
spaceLock.acquireUninterruptibly(); spaceLock.acquireUninterruptibly();
registerPhysicsObject(body); this.registerPhysicsObject(body);
bodyPointerMap.put(body,collidable); bodyPointerMap.put(body,collidable);
collidableList.add(collidable); collidableList.add(collidable);
spaceLock.release(); spaceLock.release();
@ -688,9 +698,16 @@ public class CollisionEngine {
return data.collisionPosition; return data.collisionPosition;
} }
/**
* Registers a body
* @param body The body
*/
public void registerPhysicsObject(DBody body){ public void registerPhysicsObject(DBody body){
if(!bodies.contains(body)){ if(!bodies.contains(body)){
bodies.add(body); bodies.add(body);
if(bodies.size() > COLLIDABLE_COUNT_WARNING_THRESHOLD){
LoggerInterface.loggerEngine.WARNING("Body count has superceded the warning threshold! " + bodies.size());
}
// OdeHelper.createBody(world); // OdeHelper.createBody(world);
} }
} }
@ -699,7 +716,7 @@ public class CollisionEngine {
* Destroys a body and all geometry under the body * Destroys a body and all geometry under the body
* @param body The DBody to destroy * @param body The DBody to destroy
*/ */
private void deregisterPhysicsObject(DBody body){ protected void destroyDBody(DBody body){
spaceLock.acquireUninterruptibly(); spaceLock.acquireUninterruptibly();
if(bodies.contains(body)){ if(bodies.contains(body)){
bodies.remove(body); bodies.remove(body);
@ -734,7 +751,7 @@ public class CollisionEngine {
this.deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e)); this.deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e));
e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY); e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
if(rigidBody != null){ if(rigidBody != null){
this.deregisterPhysicsObject(rigidBody); this.destroyDBody(rigidBody);
} }
} }
if(ServerPhysicsSyncTree.hasTree(e)){ if(ServerPhysicsSyncTree.hasTree(e)){
@ -1084,7 +1101,11 @@ public class CollisionEngine {
* @param geom The geometry * @param geom The geometry
*/ */
protected void destroyGeom(DGeom geom){ protected void destroyGeom(DGeom geom){
spaceLock.acquireUninterruptibly();
this.space.remove(geom);
geom.DESTRUCTOR();
geom.destroy(); geom.destroy();
spaceLock.release();
} }
/** /**

View File

@ -1,5 +1,8 @@
package electrosphere.collision; package electrosphere.collision;
import java.util.LinkedList;
import java.util.List;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
@ -11,6 +14,8 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags; import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.ServerEntityUtils;
import electrosphere.entity.state.collidable.ClientCollidableTree; import electrosphere.entity.state.collidable.ClientCollidableTree;
import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree;
import electrosphere.entity.state.physicssync.ClientPhysicsSyncTree; import electrosphere.entity.state.physicssync.ClientPhysicsSyncTree;
@ -485,6 +490,24 @@ public class PhysicsEntityUtils {
return terrainBody; return terrainBody;
} }
/**
* Repositions all active physics-scoped entities on a given realm
* @param collisionEngine The realm's collision engine
*/
public static void serverRepositionEntities(CollisionEngine collisionEngine){
List<Entity> toReposition = new LinkedList<Entity>();
for(Collidable collidable : collisionEngine.getCollidables()){
Entity entity = collidable.getParent();
DBody body = PhysicsEntityUtils.getDBody(entity);
if(body != null && body.isEnabled() && !body.isKinematic()){
toReposition.add(entity);
}
}
for(Entity parent : toReposition){
ServerEntityUtils.repositionEntity(parent,EntityUtils.getPosition(parent));
}
}
/** /**
* Gets the transform from parent entity position to rigid body * Gets the transform from parent entity position to rigid body
* @param entity The entity * @param entity The entity

View File

@ -120,5 +120,14 @@ public class PhysicsUtils {
collisionEngine.setBodyTransform(body, template, position, rotation, scale); collisionEngine.setBodyTransform(body, template, position, rotation, scale);
} }
/**
* Destroys a body
* @param collisionEngine The collision engine
* @param body The body
*/
public static void destroyBody(CollisionEngine collisionEngine, DBody body){
collisionEngine.destroyDBody(body);
}
} }

View File

@ -7,6 +7,7 @@ import org.joml.Vector3d;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.state.attach.AttachUtils; import electrosphere.entity.state.attach.AttachUtils;
import electrosphere.entity.state.hitbox.HitboxCollectionState;
import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.renderer.actor.ActorUtils; import electrosphere.renderer.actor.ActorUtils;
@ -64,6 +65,7 @@ public class ClientEntityUtils {
if(Globals.clientScene != null){ if(Globals.clientScene != null){
Globals.clientScene.deregisterEntity(entity); Globals.clientScene.deregisterEntity(entity);
} }
HitboxCollectionState.destroyHitboxState(entity,false);
if(entity == Globals.playerEntity && Globals.firstPersonEntity != null){ if(entity == Globals.playerEntity && Globals.firstPersonEntity != null){
ClientEntityUtils.destroyEntity(Globals.firstPersonEntity); ClientEntityUtils.destroyEntity(Globals.firstPersonEntity);
} }

View File

@ -56,6 +56,7 @@ public class EntityCreationUtils {
if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){ if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){
Globals.entityDataCellMapper.registerEntity(rVal, cell); Globals.entityDataCellMapper.registerEntity(rVal, cell);
ServerDataCell mapping = Globals.entityDataCellMapper.getEntityDataCell(rVal);
throw new Error("Failed to map entity to cell!"); throw new Error("Failed to map entity to cell!");
} }

View File

@ -55,7 +55,7 @@ public class ServerEntityUtils {
} }
/** /**
* Called to reposition the creature * Called to reposition the entity
* @param entity * @param entity
* @param position * @param position
*/ */
@ -63,10 +63,25 @@ public class ServerEntityUtils {
if(position == null){ if(position == null){
throw new Error("Trying to set server entity position to null!"); throw new Error("Trying to set server entity position to null!");
} }
if(AttachUtils.getParent(entity) != null){
throw new Error("Trying to reposition attached entity!");
}
Realm realm = Globals.realmManager.getEntityRealm(entity); Realm realm = Globals.realmManager.getEntityRealm(entity);
if(position.x < 0 || position.y < 0 || position.z < 0){ if(position.x < 0 || position.y < 0 || position.z < 0){
throw new Error("Providing invalid location to reposition! " + position); throw new Error("Providing invalid location to reposition! " + position);
} }
ServerEntityUtils.repositionEntityRecursive(realm, entity, position);
//reposition entity
CollisionObjUtils.serverPositionCharacter(entity, position);
}
/**
* Called to reposition the entity
* @param realm The realm containing the entity
* @param entity The entity
* @param position The new position for the entity
*/
protected static void repositionEntityRecursive(Realm realm, Entity entity, Vector3d position){
//if server, get current server data cell //if server, get current server data cell
ServerDataCell oldDataCell = Globals.entityDataCellMapper.getEntityDataCell(entity); ServerDataCell oldDataCell = Globals.entityDataCellMapper.getEntityDataCell(entity);
ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position); ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position);
@ -92,8 +107,12 @@ public class ServerEntityUtils {
throw new Error("Entity not removed from scene!"); throw new Error("Entity not removed from scene!");
} }
} }
//reposition entity if(AttachUtils.hasChildren(entity)){
CollisionObjUtils.serverPositionCharacter(entity, position); List<Entity> children = AttachUtils.getChildrenList(entity);
for(Entity child : children){
repositionEntityRecursive(realm, child, position);
}
}
} }
/** /**
@ -105,15 +124,6 @@ public class ServerEntityUtils {
throw new IllegalArgumentException("Trying to destroy null!"); throw new IllegalArgumentException("Trying to destroy null!");
} }
//
//destroy the child entities, too
if(AttachUtils.hasChildren(entity)){
List<Entity> children = AttachUtils.getChildrenList(entity);
for(Entity child : children){
ServerEntityUtils.destroyEntity(child);
}
}
// //
//get info required to destroy //get info required to destroy
Realm realm = Globals.realmManager.getEntityRealm(entity); Realm realm = Globals.realmManager.getEntityRealm(entity);
@ -136,7 +146,7 @@ public class ServerEntityUtils {
// //
//detatch from all global tracking //detatch from all global tracking
HitboxCollectionState.destroyHitboxState(entity); HitboxCollectionState.destroyHitboxState(entity,true);
Globals.realmManager.removeEntity(entity); Globals.realmManager.removeEntity(entity);
EntityLookupUtils.removeEntity(entity); EntityLookupUtils.removeEntity(entity);
if(Globals.aiManager != null){ if(Globals.aiManager != null){
@ -146,6 +156,15 @@ public class ServerEntityUtils {
// //
//deregister all behavior trees //deregister all behavior trees
EntityUtils.cleanUpEntity(entity); EntityUtils.cleanUpEntity(entity);
//
//destroy the child entities, too
if(AttachUtils.hasChildren(entity)){
List<Entity> children = AttachUtils.getChildrenList(entity);
for(Entity child : children){
ServerEntityUtils.destroyEntity(child);
}
}
} }
/** /**

View File

@ -18,6 +18,7 @@ import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.hitbox.HitboxManager; import electrosphere.collision.hitbox.HitboxManager;
import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback; import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
@ -26,6 +27,7 @@ import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState.Hitbo
import electrosphere.game.data.collidable.HitboxData; import electrosphere.game.data.collidable.HitboxData;
import electrosphere.game.data.utils.DataFormatUtil; import electrosphere.game.data.utils.DataFormatUtil;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.Realm;
import electrosphere.util.math.SpatialMathUtils; import electrosphere.util.math.SpatialMathUtils;
/** /**
@ -518,16 +520,37 @@ public class HitboxCollectionState {
/** /**
* Destroys the hitbox state and removes it from the entity * Destroys the hitbox state and removes it from the entity
* @param entity the entity * @param entity the entity
* @param isServer true if this is the server, false otherwise
* @return The hitbox state if it exists, null otherwise * @return The hitbox state if it exists, null otherwise
*/ */
public static HitboxCollectionState destroyHitboxState(Entity entity){ public static HitboxCollectionState destroyHitboxState(Entity entity, boolean isServer){
HitboxCollectionState state = null; HitboxCollectionState state = null;
if(hasHitboxState(entity)){ if(HitboxCollectionState.hasHitboxState(entity)){
state = getHitboxState(entity); state = HitboxCollectionState.getHitboxState(entity);
state.manager.deregisterHitbox(state); state.manager.deregisterHitbox(state);
state.destroy(isServer);
} }
return state; return state;
} }
/**
* Destroys the content of the state
* @param true if this is the server, false otherwise
*/
protected void destroy(boolean isServer){
CollisionEngine engine = null;
if(isServer){
Realm realm = Globals.realmManager.getEntityRealm(parent);
if(realm != null){
engine = realm.getHitboxManager().getCollisionEngine();
}
} else {
engine = Globals.clientSceneWrapper.getHitboxManager().getCollisionEngine();
}
if(engine != null){
PhysicsUtils.destroyBody(engine, body);
}
}
/** /**
* Gets whether the hitbox state is active or not * Gets whether the hitbox state is active or not

View File

@ -451,7 +451,7 @@ public class ItemUtils {
//this deregisters from all four & unhooks rigid bodies from the physics runtime //this deregisters from all four & unhooks rigid bodies from the physics runtime
Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(item); Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(item);
//destroy hitboxes //destroy hitboxes
HitboxCollectionState.destroyHitboxState(item); HitboxCollectionState.destroyHitboxState(item,false);
//destroy graphics //destroy graphics
ClientEntityUtils.destroyEntity(item); ClientEntityUtils.destroyEntity(item);
} }

View File

@ -40,6 +40,9 @@ public class EntityDataCellMapper {
* @param serverDataCell The new server data cell for the entity * @param serverDataCell The new server data cell for the entity
*/ */
public void updateEntityCell(Entity entity, ServerDataCell serverDataCell){ public void updateEntityCell(Entity entity, ServerDataCell serverDataCell){
if(serverDataCell == null){
throw new Error("Passing null to cell mapper update! " + entity + " " + serverDataCell);
}
entityDataCellMap.put(entity, serverDataCell); entityDataCellMap.put(entity, serverDataCell);
} }

View File

@ -164,11 +164,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
for(int x = worldPos.x - playerSimulationRadius; x < worldPos.x + playerSimulationRadius + 1; x++){ 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 y = worldPos.y - playerSimulationRadius; y < worldPos.y + playerSimulationRadius + 1; y++){
for(int z = worldPos.z - playerSimulationRadius; z < worldPos.z + playerSimulationRadius + 1; z++){ for(int z = worldPos.z - playerSimulationRadius; z < worldPos.z + playerSimulationRadius + 1; z++){
if( if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(new Vector3i(x,y,z), worldPos, playerSimulationRadius)){
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete()
){
Vector3i targetPos = new Vector3i(x,y,z); Vector3i targetPos = new Vector3i(x,y,z);
LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z); LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z);
loadedCellsLock.acquireUninterruptibly(); loadedCellsLock.acquireUninterruptibly();
@ -199,21 +195,10 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
*/ */
public void movePlayer(Player player, Vector3i newPosition){ public void movePlayer(Player player, Vector3i newPosition){
int playerSimulationRadius = player.getSimulationRadius(); int playerSimulationRadius = player.getSimulationRadius();
Vector3i oldPosition = player.getWorldPos();
player.setWorldPos(newPosition); player.setWorldPos(newPosition);
for(ServerDataCell cell : this.groundDataCells.values()){ for(ServerDataCell cell : this.groundDataCells.values()){
Vector3i worldPos = this.getCellWorldPosition(cell); Vector3i worldPos = this.getCellWorldPosition(cell);
if( if(cell.containsPlayer(player) && !this.shouldContainPlayer(worldPos, newPosition, playerSimulationRadius)){
cell.containsPlayer(player) &&
(
worldPos.x < newPosition.x - playerSimulationRadius ||
worldPos.x > newPosition.x + playerSimulationRadius ||
worldPos.y < newPosition.y - playerSimulationRadius ||
worldPos.y > newPosition.y + playerSimulationRadius ||
worldPos.z < newPosition.z - playerSimulationRadius ||
worldPos.z > newPosition.z + playerSimulationRadius
)
){
cell.removePlayer(player); cell.removePlayer(player);
this.broadcastDestructionToPlayer(player, cell); this.broadcastDestructionToPlayer(player, cell);
if(cell.getScene().containsEntity(player.getPlayerEntity())){ if(cell.getScene().containsEntity(player.getPlayerEntity())){
@ -230,19 +215,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
for(int x = newPosition.x - playerSimulationRadius; x < newPosition.x + playerSimulationRadius + 1; x++){ 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 y = newPosition.y - playerSimulationRadius; y < newPosition.y + playerSimulationRadius + 1; y++){
for(int z = newPosition.x - playerSimulationRadius; z < newPosition.z + playerSimulationRadius + 1; z++){ for(int z = newPosition.x - playerSimulationRadius; z < newPosition.z + playerSimulationRadius + 1; z++){
if( if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(new Vector3i(x, y, z), newPosition, playerSimulationRadius)){
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete() &&
(
x < oldPosition.x - playerSimulationRadius ||
x > oldPosition.x + playerSimulationRadius ||
y < oldPosition.y - playerSimulationRadius ||
y > oldPosition.y + playerSimulationRadius ||
z < oldPosition.z - playerSimulationRadius ||
z > oldPosition.z + playerSimulationRadius
)
){
Vector3i targetPos = new Vector3i(x,y,z); Vector3i targetPos = new Vector3i(x,y,z);
if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){ if(groundDataCells.get(getServerDataCellKey(targetPos)) != null){
loadedCellsLock.acquireUninterruptibly(); loadedCellsLock.acquireUninterruptibly();
@ -266,6 +239,38 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
} }
} }
/**
* Checks if a player should be contained in a cell
* @param cellWorldPos The world position of the cell
* @param playerPos The world position of the player
* @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;
}
/**
* Checks if a cell can be created at the position
* @param cellPos The position to check
* @return true if a cell can be created at that position, false otherwise
*/
private boolean canCreateCell(Vector3i cellPos){
return this.canCreateCell(cellPos.x, cellPos.y, cellPos.z);
}
/**
* Checks if a cell can be created at the position
* @return true if a cell can be created at that position, false otherwise
*/
private boolean canCreateCell(int x, int y, int z){
return
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete()
;
}
/** /**
* Broadcasts messages to player to destroy all entities in a given cell * Broadcasts messages to player to destroy all entities in a given cell
* @param player The player * @param player The player
@ -314,17 +319,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
//remove from cells that are out of range //remove from cells that are out of range
for(ServerDataCell cell : this.groundDataCells.values()){ for(ServerDataCell cell : this.groundDataCells.values()){
Vector3i cellWorldPos = this.getCellWorldPosition(cell); Vector3i cellWorldPos = this.getCellWorldPosition(cell);
if( if(cell.containsPlayer(player) && !this.shouldContainPlayer(cellWorldPos, newPosition, playerSimulationRadius)){
cell.containsPlayer(player) &&
(
cellWorldPos.x < newPosition.x - playerSimulationRadius ||
cellWorldPos.x > newPosition.x + playerSimulationRadius ||
cellWorldPos.y < newPosition.y - playerSimulationRadius ||
cellWorldPos.y > newPosition.y + playerSimulationRadius ||
cellWorldPos.z < newPosition.z - playerSimulationRadius ||
cellWorldPos.z > newPosition.z + playerSimulationRadius
)
){
if(cell.getScene().containsEntity(player.getPlayerEntity())){ if(cell.getScene().containsEntity(player.getPlayerEntity())){
throw new Error("Trying to remove player from a cell that contains its entity!"); throw new Error("Trying to remove player from a cell that contains its entity!");
} }
@ -337,11 +332,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
for(int x = newPosition.x - playerSimulationRadius + 1; x < newPosition.x + playerSimulationRadius; x++){ 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 y = newPosition.y - playerSimulationRadius + 1; y < newPosition.y + playerSimulationRadius; y++){
for(int z = newPosition.x - playerSimulationRadius + 1; z < newPosition.z + playerSimulationRadius; z++){ for(int z = newPosition.x - playerSimulationRadius + 1; z < newPosition.z + playerSimulationRadius; z++){
if( if(this.canCreateCell(x,y,z) && this.shouldContainPlayer(new Vector3i(x,y,z), newPosition, playerSimulationRadius)){
x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() &&
y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() &&
z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete()
){
Vector3i targetPos = new Vector3i(x,y,z); Vector3i targetPos = new Vector3i(x,y,z);
if(groundDataCells.get(this.getServerDataCellKey(targetPos)) != null){ if(groundDataCells.get(this.getServerDataCellKey(targetPos)) != null){
loadedCellsLock.acquireUninterruptibly(); loadedCellsLock.acquireUninterruptibly();
@ -498,14 +489,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
* @return The data cell if created, null otherwise * @return The data cell if created, null otherwise
*/ */
public ServerDataCell tryCreateCellAtPoint(Vector3i worldPos){ public ServerDataCell tryCreateCellAtPoint(Vector3i worldPos){
if( if(this.canCreateCell(worldPos) && groundDataCells.get(this.getServerDataCellKey(worldPos)) == null){
//in bounds of array
worldPos.x >= 0 && worldPos.x < this.serverWorldData.getWorldSizeDiscrete() &&
worldPos.y >= 0 && worldPos.y < this.serverWorldData.getWorldSizeDiscrete() &&
worldPos.z >= 0 && worldPos.z < this.serverWorldData.getWorldSizeDiscrete() &&
//isn't null
groundDataCells.get(this.getServerDataCellKey(worldPos)) == null
){
loadedCellsLock.acquireUninterruptibly(); loadedCellsLock.acquireUninterruptibly();
//create data cell //create data cell
this.createServerDataCell(worldPos); this.createServerDataCell(worldPos);
@ -530,14 +514,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
* @return The data cell if found, null otherwise * @return The data cell if found, null otherwise
*/ */
public ServerDataCell getCellAtWorldPosition(Vector3i position){ public ServerDataCell getCellAtWorldPosition(Vector3i position){
if( if(this.canCreateCell(position) && groundDataCells.get(this.getServerDataCellKey(position)) != null){
//in bounds of array
position.x >= 0 && position.x < this.serverWorldData.getWorldSizeDiscrete() &&
position.y >= 0 && position.y < this.serverWorldData.getWorldSizeDiscrete() &&
position.z >= 0 && position.z < this.serverWorldData.getWorldSizeDiscrete() &&
//isn't null
groundDataCells.get(this.getServerDataCellKey(position)) != null
){
return groundDataCells.get(this.getServerDataCellKey(position)); return groundDataCells.get(this.getServerDataCellKey(position));
} }
return null; return null;
@ -563,6 +540,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
} }
} }
loadedCellsLock.release(); loadedCellsLock.release();
this.unloadPlayerlessChunks();
this.updatePlayerPositions(); this.updatePlayerPositions();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }

View File

@ -1,6 +1,7 @@
package electrosphere.server.datacell; package electrosphere.server.datacell;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.hitbox.HitboxManager; import electrosphere.collision.hitbox.HitboxManager;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
@ -193,6 +194,7 @@ public class Realm {
if(Globals.RUN_PHYSICS){ if(Globals.RUN_PHYSICS){
collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime());
collisionEngine.updateDynamicObjectTransforms(); collisionEngine.updateDynamicObjectTransforms();
PhysicsEntityUtils.serverRepositionEntities(collisionEngine);
chemistryEngine.collide(); chemistryEngine.collide();
} }
// //