From 9a20a64d5bc79603f564d26ab287b0ff31982d65 Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 13 Nov 2024 21:08:32 -0500 Subject: [PATCH] fixing up gridded data cell manager --- docs/src/progress/renderertodo.md | 4 + .../debug/entity/ImGuiEntityDebugActions.java | 33 ++++++ .../menu/debug/entity/ImGuiEntityMacros.java | 5 + .../collision/CollisionEngine.java | 27 ++++- .../collision/PhysicsEntityUtils.java | 23 ++++ .../electrosphere/collision/PhysicsUtils.java | 9 ++ .../entity/ClientEntityUtils.java | 2 + .../entity/EntityCreationUtils.java | 1 + .../entity/ServerEntityUtils.java | 45 +++++--- .../state/hitbox/HitboxCollectionState.java | 29 ++++- .../entity/types/item/ItemUtils.java | 2 +- .../server/datacell/EntityDataCellMapper.java | 3 + .../datacell/GriddedDataCellManager.java | 102 +++++++----------- .../electrosphere/server/datacell/Realm.java | 2 + 14 files changed, 205 insertions(+), 82 deletions(-) create mode 100644 src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityDebugActions.java diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 5e090a7b..3d268472 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1016,6 +1016,10 @@ Ability to replacing a player's entity Fix shadows on main shader Button to swap between player entity and editor entity 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 diff --git a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityDebugActions.java b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityDebugActions.java new file mode 100644 index 00000000..84207bd6 --- /dev/null +++ b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityDebugActions.java @@ -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(); + } + } + +} diff --git a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java index 8fc54915..fc633317 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/entity/ImGuiEntityMacros.java @@ -63,6 +63,7 @@ public class ImGuiEntityMacros { private static boolean showLinkedEntitiesTab = false;//show linked entities private static boolean showServerViewDirTab = false; //show server view dir private static boolean showPhysicsTab = false; //show physics values + private static boolean showDebugActionsTab = false; //show debug actions /** * Creates the windows in this file @@ -164,6 +165,9 @@ public class ImGuiEntityMacros { if(HitboxCollectionState.hasHitboxState(detailViewEntity) && ImGui.checkbox("Hitbox State", showHitboxTab)){ showHitboxTab = !showHitboxTab; } + if(ImGui.checkbox("Debug Actions", showDebugActionsTab)){ + showDebugActionsTab = !showDebugActionsTab; + } ImGui.treePop(); } ImGui.nextColumn(); @@ -176,6 +180,7 @@ public class ImGuiEntityMacros { ImGuiEntityMacros.drawLinkedEntities(); ImGuiEntityMacros.drawServerViewDir(); ImGuiEntityMacros.drawPhysicsDetails(); + ImGuiEntityDebugActions.drawDebugActions(showDebugActionsTab, detailViewEntity); ImGuiEntityMacros.drawDataView(); } }); diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java index 50119bc1..eb3dc434 100644 --- a/src/main/java/electrosphere/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/collision/CollisionEngine.java @@ -84,6 +84,11 @@ public class CollisionEngine { * This keeps the physics simulation much more stable than it would be otherwise. */ 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 CollisionWorldData collisionWorldData; @@ -577,9 +582,14 @@ public class CollisionEngine { 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){ spaceLock.acquireUninterruptibly(); - registerPhysicsObject(body); + this.registerPhysicsObject(body); bodyPointerMap.put(body,collidable); collidableList.add(collidable); spaceLock.release(); @@ -688,9 +698,16 @@ public class CollisionEngine { return data.collisionPosition; } + /** + * Registers a body + * @param body The body + */ public void registerPhysicsObject(DBody body){ if(!bodies.contains(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); } } @@ -699,7 +716,7 @@ public class CollisionEngine { * Destroys a body and all geometry under the body * @param body The DBody to destroy */ - private void deregisterPhysicsObject(DBody body){ + protected void destroyDBody(DBody body){ spaceLock.acquireUninterruptibly(); if(bodies.contains(body)){ bodies.remove(body); @@ -734,7 +751,7 @@ public class CollisionEngine { this.deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e)); e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY); if(rigidBody != null){ - this.deregisterPhysicsObject(rigidBody); + this.destroyDBody(rigidBody); } } if(ServerPhysicsSyncTree.hasTree(e)){ @@ -1084,7 +1101,11 @@ public class CollisionEngine { * @param geom The geometry */ protected void destroyGeom(DGeom geom){ + spaceLock.acquireUninterruptibly(); + this.space.remove(geom); + geom.DESTRUCTOR(); geom.destroy(); + spaceLock.release(); } /** diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index 0ab96d1d..6cf1fa9e 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -1,5 +1,8 @@ package electrosphere.collision; +import java.util.LinkedList; +import java.util.List; + import org.joml.Matrix4d; import org.joml.Quaterniond; import org.joml.Vector3d; @@ -11,6 +14,8 @@ import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityTags; +import electrosphere.entity.EntityUtils; +import electrosphere.entity.ServerEntityUtils; import electrosphere.entity.state.collidable.ClientCollidableTree; import electrosphere.entity.state.collidable.ServerCollidableTree; import electrosphere.entity.state.physicssync.ClientPhysicsSyncTree; @@ -485,6 +490,24 @@ public class PhysicsEntityUtils { 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 toReposition = new LinkedList(); + 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 * @param entity The entity diff --git a/src/main/java/electrosphere/collision/PhysicsUtils.java b/src/main/java/electrosphere/collision/PhysicsUtils.java index eba456ed..38ec032f 100644 --- a/src/main/java/electrosphere/collision/PhysicsUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsUtils.java @@ -120,5 +120,14 @@ public class PhysicsUtils { 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); + } + } diff --git a/src/main/java/electrosphere/entity/ClientEntityUtils.java b/src/main/java/electrosphere/entity/ClientEntityUtils.java index fabb61c4..5ea4773e 100644 --- a/src/main/java/electrosphere/entity/ClientEntityUtils.java +++ b/src/main/java/electrosphere/entity/ClientEntityUtils.java @@ -7,6 +7,7 @@ import org.joml.Vector3d; import electrosphere.engine.Globals; import electrosphere.entity.state.attach.AttachUtils; +import electrosphere.entity.state.hitbox.HitboxCollectionState; import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.renderer.actor.ActorUtils; @@ -64,6 +65,7 @@ public class ClientEntityUtils { if(Globals.clientScene != null){ Globals.clientScene.deregisterEntity(entity); } + HitboxCollectionState.destroyHitboxState(entity,false); if(entity == Globals.playerEntity && Globals.firstPersonEntity != null){ ClientEntityUtils.destroyEntity(Globals.firstPersonEntity); } diff --git a/src/main/java/electrosphere/entity/EntityCreationUtils.java b/src/main/java/electrosphere/entity/EntityCreationUtils.java index 90f23a96..fcb92dd0 100644 --- a/src/main/java/electrosphere/entity/EntityCreationUtils.java +++ b/src/main/java/electrosphere/entity/EntityCreationUtils.java @@ -56,6 +56,7 @@ public class EntityCreationUtils { if(Globals.entityDataCellMapper.getEntityDataCell(rVal) == null){ Globals.entityDataCellMapper.registerEntity(rVal, cell); + ServerDataCell mapping = Globals.entityDataCellMapper.getEntityDataCell(rVal); throw new Error("Failed to map entity to cell!"); } diff --git a/src/main/java/electrosphere/entity/ServerEntityUtils.java b/src/main/java/electrosphere/entity/ServerEntityUtils.java index bea65a06..82983429 100644 --- a/src/main/java/electrosphere/entity/ServerEntityUtils.java +++ b/src/main/java/electrosphere/entity/ServerEntityUtils.java @@ -55,7 +55,7 @@ public class ServerEntityUtils { } /** - * Called to reposition the creature + * Called to reposition the entity * @param entity * @param position */ @@ -63,10 +63,25 @@ public class ServerEntityUtils { if(position == 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); if(position.x < 0 || position.y < 0 || position.z < 0){ 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 ServerDataCell oldDataCell = Globals.entityDataCellMapper.getEntityDataCell(entity); ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position); @@ -92,8 +107,12 @@ public class ServerEntityUtils { throw new Error("Entity not removed from scene!"); } } - //reposition entity - CollisionObjUtils.serverPositionCharacter(entity, position); + if(AttachUtils.hasChildren(entity)){ + List 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!"); } - // - //destroy the child entities, too - if(AttachUtils.hasChildren(entity)){ - List children = AttachUtils.getChildrenList(entity); - for(Entity child : children){ - ServerEntityUtils.destroyEntity(child); - } - } - // //get info required to destroy Realm realm = Globals.realmManager.getEntityRealm(entity); @@ -136,7 +146,7 @@ public class ServerEntityUtils { // //detatch from all global tracking - HitboxCollectionState.destroyHitboxState(entity); + HitboxCollectionState.destroyHitboxState(entity,true); Globals.realmManager.removeEntity(entity); EntityLookupUtils.removeEntity(entity); if(Globals.aiManager != null){ @@ -146,6 +156,15 @@ public class ServerEntityUtils { // //deregister all behavior trees EntityUtils.cleanUpEntity(entity); + + // + //destroy the child entities, too + if(AttachUtils.hasChildren(entity)){ + List children = AttachUtils.getChildrenList(entity); + for(Entity child : children){ + ServerEntityUtils.destroyEntity(child); + } + } } /** diff --git a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java index f46039db..a7d36205 100644 --- a/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java +++ b/src/main/java/electrosphere/entity/state/hitbox/HitboxCollectionState.java @@ -18,6 +18,7 @@ import electrosphere.collision.PhysicsUtils; import electrosphere.collision.collidable.Collidable; import electrosphere.collision.hitbox.HitboxManager; import electrosphere.collision.hitbox.HitboxUtils.HitboxPositionCallback; +import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; 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.utils.DataFormatUtil; import electrosphere.logger.LoggerInterface; +import electrosphere.server.datacell.Realm; import electrosphere.util.math.SpatialMathUtils; /** @@ -518,16 +520,37 @@ public class HitboxCollectionState { /** * Destroys the hitbox state and removes it from 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 */ - public static HitboxCollectionState destroyHitboxState(Entity entity){ + public static HitboxCollectionState destroyHitboxState(Entity entity, boolean isServer){ HitboxCollectionState state = null; - if(hasHitboxState(entity)){ - state = getHitboxState(entity); + if(HitboxCollectionState.hasHitboxState(entity)){ + state = HitboxCollectionState.getHitboxState(entity); state.manager.deregisterHitbox(state); + state.destroy(isServer); } 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 diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index e5148178..32b61d9b 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -451,7 +451,7 @@ public class ItemUtils { //this deregisters from all four & unhooks rigid bodies from the physics runtime Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(item); //destroy hitboxes - HitboxCollectionState.destroyHitboxState(item); + HitboxCollectionState.destroyHitboxState(item,false); //destroy graphics ClientEntityUtils.destroyEntity(item); } diff --git a/src/main/java/electrosphere/server/datacell/EntityDataCellMapper.java b/src/main/java/electrosphere/server/datacell/EntityDataCellMapper.java index e0488f0d..7f4da3db 100644 --- a/src/main/java/electrosphere/server/datacell/EntityDataCellMapper.java +++ b/src/main/java/electrosphere/server/datacell/EntityDataCellMapper.java @@ -40,6 +40,9 @@ public class EntityDataCellMapper { * @param serverDataCell The new server data cell for the entity */ 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); } diff --git a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java index fad7aecd..e16e0b35 100644 --- a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java @@ -164,11 +164,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager 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( - x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() && - y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() && - z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete() - ){ + if(this.canCreateCell(x, y, z) && this.shouldContainPlayer(new Vector3i(x,y,z), worldPos, playerSimulationRadius)){ Vector3i targetPos = new Vector3i(x,y,z); LoggerInterface.loggerEngine.DEBUG("GriddedDataCellManager: Add player to " + x + " " + y + " " + z); loadedCellsLock.acquireUninterruptibly(); @@ -199,21 +195,10 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager */ public void movePlayer(Player player, Vector3i newPosition){ int playerSimulationRadius = player.getSimulationRadius(); - Vector3i oldPosition = player.getWorldPos(); player.setWorldPos(newPosition); for(ServerDataCell cell : this.groundDataCells.values()){ Vector3i worldPos = this.getCellWorldPosition(cell); - if( - 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 - ) - ){ + if(cell.containsPlayer(player) && !this.shouldContainPlayer(worldPos, newPosition, playerSimulationRadius)){ cell.removePlayer(player); this.broadcastDestructionToPlayer(player, cell); 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 y = newPosition.y - playerSimulationRadius; y < newPosition.y + playerSimulationRadius + 1; y++){ for(int z = newPosition.x - playerSimulationRadius; z < newPosition.z + playerSimulationRadius + 1; z++){ - if( - 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 - ) - ){ + 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){ 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 * @param player The player @@ -314,17 +319,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager //remove from cells that are out of range for(ServerDataCell cell : this.groundDataCells.values()){ Vector3i cellWorldPos = this.getCellWorldPosition(cell); - if( - 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.containsPlayer(player) && !this.shouldContainPlayer(cellWorldPos, newPosition, playerSimulationRadius)){ if(cell.getScene().containsEntity(player.getPlayerEntity())){ 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 y = newPosition.y - playerSimulationRadius + 1; y < newPosition.y + playerSimulationRadius; y++){ for(int z = newPosition.x - playerSimulationRadius + 1; z < newPosition.z + playerSimulationRadius; z++){ - if( - x >= 0 && x < this.serverWorldData.getWorldSizeDiscrete() && - y >= 0 && y < this.serverWorldData.getWorldSizeDiscrete() && - z >= 0 && z < this.serverWorldData.getWorldSizeDiscrete() - ){ + 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){ loadedCellsLock.acquireUninterruptibly(); @@ -498,14 +489,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager * @return The data cell if created, null otherwise */ public ServerDataCell tryCreateCellAtPoint(Vector3i worldPos){ - if( - //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 - ){ + if(this.canCreateCell(worldPos) && groundDataCells.get(this.getServerDataCellKey(worldPos)) == null){ loadedCellsLock.acquireUninterruptibly(); //create data cell this.createServerDataCell(worldPos); @@ -530,14 +514,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager * @return The data cell if found, null otherwise */ public ServerDataCell getCellAtWorldPosition(Vector3i position){ - if( - //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 - ){ + if(this.canCreateCell(position) && groundDataCells.get(this.getServerDataCellKey(position)) != null){ return groundDataCells.get(this.getServerDataCellKey(position)); } return null; @@ -563,6 +540,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager } } loadedCellsLock.release(); + this.unloadPlayerlessChunks(); this.updatePlayerPositions(); Globals.profiler.endCpuSample(); } diff --git a/src/main/java/electrosphere/server/datacell/Realm.java b/src/main/java/electrosphere/server/datacell/Realm.java index cb893f24..827eb5a9 100644 --- a/src/main/java/electrosphere/server/datacell/Realm.java +++ b/src/main/java/electrosphere/server/datacell/Realm.java @@ -1,6 +1,7 @@ package electrosphere.server.datacell; import electrosphere.collision.CollisionEngine; +import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.hitbox.HitboxManager; import electrosphere.engine.Globals; import electrosphere.entity.Entity; @@ -193,6 +194,7 @@ public class Realm { if(Globals.RUN_PHYSICS){ collisionEngine.simulatePhysics((float)Globals.timekeeper.getSimFrameTime()); collisionEngine.updateDynamicObjectTransforms(); + PhysicsEntityUtils.serverRepositionEntities(collisionEngine); chemistryEngine.collide(); } //