From b0277f9f74677e39b6014497013585465d40a4da Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 14 Aug 2024 13:33:29 -0400 Subject: [PATCH] properly delete entities on the server --- docs/src/progress/currenttarget.md | 1 - docs/src/progress/renderertodo.md | 2 + .../client/fluid/cells/FluidCell.java | 2 +- .../client/terrain/cells/DrawCell.java | 2 +- .../collision/CollisionEngine.java | 25 ++++++- .../collision/PhysicsEntityUtils.java | 9 +++ src/main/java/electrosphere/entity/Scene.java | 4 +- .../entity/ServerEntityUtils.java | 33 ++++++++- .../entity/state/equip/ClientEquipState.java | 8 +- .../entity/state/equip/ServerEquipState.java | 7 +- .../physicssync/ServerPhysicsSyncTree.java | 74 ++++++++++--------- .../entity/types/item/ItemUtils.java | 2 +- .../datacell/physics/PhysicsDataCell.java | 2 +- .../utils/ServerBehaviorTreeUtils.java | 2 +- 14 files changed, 116 insertions(+), 57 deletions(-) diff --git a/docs/src/progress/currenttarget.md b/docs/src/progress/currenttarget.md index 754dc90e..1c098dd8 100644 --- a/docs/src/progress/currenttarget.md +++ b/docs/src/progress/currenttarget.md @@ -16,7 +16,6 @@ Stability Movement penalty while swinging weapon Transition animation for blocking with two hands - Strafing walking animation + bug fixes Fix grass rendering distance diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index d5ce1bdd..9d09bc9b 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -597,6 +597,8 @@ Fix hitbox placement does not scale with entity scale on server Fix not all grass tiles update when updating a nearby voxel (ie it doesn't go into negative coordinates to scan for foliage updates) +Fix typescript load error + Refactor menu clases under electrosphere.client package Allow texture map to bind multiple model paths to a single set of mesh->textures diff --git a/src/main/java/electrosphere/client/fluid/cells/FluidCell.java b/src/main/java/electrosphere/client/fluid/cells/FluidCell.java index 052b3217..4147efe0 100644 --- a/src/main/java/electrosphere/client/fluid/cells/FluidCell.java +++ b/src/main/java/electrosphere/client/fluid/cells/FluidCell.java @@ -84,7 +84,7 @@ public class FluidCell { */ public void destroy(){ CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); - collisionEngine.destroyEntityThatHasPhysics(modelEntity); + collisionEngine.destroyPhysics(modelEntity); EntityUtils.cleanUpEntity(modelEntity); //destruct model String modelPath = (String)modelEntity.getData(EntityDataStrings.DATA_STRING_MODEL_PATH); diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java index 2bd9a1a6..2db4f0af 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCell.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCell.java @@ -101,7 +101,7 @@ public class DrawCell { */ public void destroy(){ CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine(); - collisionEngine.destroyEntityThatHasPhysics(modelEntity); + collisionEngine.destroyPhysics(modelEntity); EntityUtils.cleanUpEntity(modelEntity); } diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java index bdae2ffa..9802f084 100644 --- a/src/main/java/electrosphere/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/collision/CollisionEngine.java @@ -51,6 +51,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.collidable.Impulse; +import electrosphere.entity.state.physicssync.ServerPhysicsSyncTree; import electrosphere.game.data.collidable.CollidableTemplate; import electrosphere.game.data.collidable.HitboxData; import electrosphere.logger.LoggerInterface; @@ -478,6 +479,17 @@ public class CollisionEngine { collidableList.add(collidable); spaceLock.release(); } + + /** + * Deregisters a collidable from the physics engine + * @param collidable The collidable + */ + public void deregisterCollisionObject(DBody body, Collidable collidable){ + spaceLock.acquireUninterruptibly(); + bodyPointerMap.remove(body); + collidableList.remove(collidable); + spaceLock.release(); + } public void listBodyPositions(){ for(DBody body : bodies){ @@ -581,7 +593,7 @@ public class CollisionEngine { * Destroys a body and all geometry under the body * @param body The DBody to destroy */ - public void deregisterPhysicsObject(DBody body){ + private void deregisterPhysicsObject(DBody body){ spaceLock.acquireUninterruptibly(); if(bodies.contains(body)){ bodies.remove(body); @@ -596,12 +608,21 @@ public class CollisionEngine { spaceLock.release(); } - public void destroyEntityThatHasPhysics(Entity e){ + /** + * Destroys the physics on an entity + * @param e The entity + */ + public void destroyPhysics(Entity e){ //make uncollidable if(e.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY)){ DBody rigidBody = (DBody)e.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); + deregisterCollisionObject(rigidBody,PhysicsEntityUtils.getCollidable(e)); + e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY); deregisterPhysicsObject(rigidBody); } + if(ServerPhysicsSyncTree.hasTree(e)){ + ServerPhysicsSyncTree.detachTree(e, ServerPhysicsSyncTree.getTree(e)); + } } /** diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index 79c54e6d..acafdebb 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -311,5 +311,14 @@ public class PhysicsEntityUtils { public static void setGeometryPosition(CollisionEngine collisionEngine, DGeom geom, Vector3d position, Quaterniond rotation){ collisionEngine.setGeomTransform(geom, position, rotation); } + + /** + * Gets the collidable attached to the entity + * @param entity The entity + * @return The collidable if it exists, null otherwise + */ + public static Collidable getCollidable(Entity entity){ + return (Collidable)entity.getData(EntityDataStrings.PHYSICS_COLLIDABLE); + } } diff --git a/src/main/java/electrosphere/entity/Scene.java b/src/main/java/electrosphere/entity/Scene.java index 3eb18735..75aa69a3 100644 --- a/src/main/java/electrosphere/entity/Scene.java +++ b/src/main/java/electrosphere/entity/Scene.java @@ -134,7 +134,9 @@ public class Scene { * @param tree The behavior tree to deregister */ public void deregisterBehaviorTree(BehaviorTree tree){ - behaviorTreeList.remove(tree); + while(behaviorTreeList.contains(tree)){ + behaviorTreeList.remove(tree); + } } /** diff --git a/src/main/java/electrosphere/entity/ServerEntityUtils.java b/src/main/java/electrosphere/entity/ServerEntityUtils.java index dec1b0f3..91d0496a 100644 --- a/src/main/java/electrosphere/entity/ServerEntityUtils.java +++ b/src/main/java/electrosphere/entity/ServerEntityUtils.java @@ -1,9 +1,12 @@ package electrosphere.entity; +import java.util.List; + import org.joml.Vector3d; import electrosphere.engine.Globals; import electrosphere.entity.state.hitbox.HitboxCollectionState; +import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.server.datacell.Realm; @@ -82,18 +85,42 @@ public class ServerEntityUtils { * @param entity the entity to destroy */ public static void destroyEntity(Entity entity){ + // + //get info required to destroy ServerDataCell cell = DataCellSearchUtils.getEntityDataCell(entity); Realm realm = Globals.realmManager.getEntityRealm(entity); + + // + //destroy the child entities, too + if(AttachUtils.hasChildren(entity)){ + List children = AttachUtils.getChildrenList(entity); + for(Entity child : children){ + ServerEntityUtils.destroyEntity(child); + } + } + + // + //cell specific logic if(cell != null){ cell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(entity.getId())); - - //if the entity had physics, remove them from the world - realm.getCollisionEngine().destroyEntityThatHasPhysics(entity); + cell.getScene().deregisterEntity(entity); } + + // + //realm specific logic + if(realm != null){ + realm.getCollisionEngine().destroyPhysics(entity); + } + + // + //detatch from all global tracking HitboxCollectionState.destroyHitboxState(entity); ServerBehaviorTreeUtils.deregisterEntity(entity); Globals.realmManager.removeEntity(entity); EntityLookupUtils.removeEntity(entity); + Globals.aiManager.removeAI(entity); + + // //deregister all behavior trees EntityUtils.cleanUpEntity(entity); } diff --git a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java index de9a7bc8..2f61d61f 100644 --- a/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java +++ b/src/main/java/electrosphere/entity/state/equip/ClientEquipState.java @@ -6,8 +6,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import org.ode4j.ode.DBody; - import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityCreationUtils; @@ -154,8 +152,7 @@ public class ClientEquipState implements BehaviorTree { } //make uncollidable if(toEquip.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ - DBody rigidBody = (DBody)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); - Globals.clientSceneWrapper.getCollisionEngine().deregisterPhysicsObject(rigidBody); + Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(toEquip); } //hide toEquip actor EntityUtils.setDraw(toEquip, false); @@ -194,8 +191,7 @@ public class ClientEquipState implements BehaviorTree { ); } if(toEquip.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ - DBody rigidBody = (DBody)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); - Globals.clientSceneWrapper.getCollisionEngine().deregisterPhysicsObject(rigidBody); + Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(toEquip); } Globals.clientSceneWrapper.getScene().removeEntityFromTag(toEquip, EntityTags.TARGETABLE); GravityUtils.clientAttemptDeactivateGravity(toEquip); diff --git a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java index 9d23871a..ee96dab6 100644 --- a/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java +++ b/src/main/java/electrosphere/entity/state/equip/ServerEquipState.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; import org.joml.Vector3d; -import org.ode4j.ode.DBody; import electrosphere.engine.Globals; import electrosphere.entity.Entity; @@ -126,9 +125,8 @@ public class ServerEquipState implements BehaviorTree { ); //make uncollidable if(inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ - DBody rigidBody = (DBody)inWorldItem.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); Realm inWorldRealm = Globals.realmManager.getEntityRealm(inWorldItem); - inWorldRealm.getCollisionEngine().deregisterPhysicsObject(rigidBody); + inWorldRealm.getCollisionEngine().destroyPhysics(inWorldItem); } //hide toEquip actor EntityUtils.setDraw(inWorldItem, false); @@ -148,9 +146,8 @@ public class ServerEquipState implements BehaviorTree { AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson()) ); if(inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && inWorldItem.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ - DBody rigidBody = (DBody)inWorldItem.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); Realm inWorldRealm = Globals.realmManager.getEntityRealm(inWorldItem); - inWorldRealm.getCollisionEngine().deregisterPhysicsObject(rigidBody); + inWorldRealm.getCollisionEngine().destroyPhysics(inWorldItem); } ServerEntityTagUtils.removeTagFromEntity(inWorldItem, EntityTags.TARGETABLE); GravityUtils.serverAttemptDeactivateGravity(inWorldItem); diff --git a/src/main/java/electrosphere/entity/state/physicssync/ServerPhysicsSyncTree.java b/src/main/java/electrosphere/entity/state/physicssync/ServerPhysicsSyncTree.java index a841f548..ccbfbde0 100644 --- a/src/main/java/electrosphere/entity/state/physicssync/ServerPhysicsSyncTree.java +++ b/src/main/java/electrosphere/entity/state/physicssync/ServerPhysicsSyncTree.java @@ -11,6 +11,7 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; +import electrosphere.logger.LoggerInterface; import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.server.datacell.utils.DataCellSearchUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; @@ -44,40 +45,44 @@ public class ServerPhysicsSyncTree implements BehaviorTree { Vector3d position = EntityUtils.getPosition(parent); Quaterniond rotation = EntityUtils.getRotation(parent); DBody body = PhysicsEntityUtils.getDBody(parent); - //velocities - Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel()); - Vector3d angularVel = PhysicsUtils.odeVecToJomlVec(body.getAngularVel()); - //forces - Vector3d linearForce = PhysicsUtils.odeVecToJomlVec(body.getForce()); - Vector3d angularForce = PhysicsUtils.odeVecToJomlVec(body.getTorque()); - if(position.distance(lastSentPosition) > UPDATE_THRESHOLD || 1.0 - rotation.dot(lastSentRotation) > UPDATE_THRESHOLD){ - lastSentPosition.set(position); - lastSentRotation.set(rotation); - DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( - EntityMessage.constructsyncPhysicsMessage( - parent.getId(), - Globals.timekeeper.getNumberOfSimFramesElapsed(), - position.x, - position.y, - position.z, - rotation.x, - rotation.y, - rotation.z, - rotation.w, - linearVel.x, - linearVel.y, - linearVel.z, - angularVel.x, - angularVel.y, - angularVel.z, - linearForce.x, - linearForce.y, - linearForce.z, - angularForce.x, - angularForce.y, - angularForce.z - ) - ); + if(body == null){ + LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Running physics sync tree on entity that does not have a physics body!")); + } else { + //velocities + Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel()); + Vector3d angularVel = PhysicsUtils.odeVecToJomlVec(body.getAngularVel()); + //forces + Vector3d linearForce = PhysicsUtils.odeVecToJomlVec(body.getForce()); + Vector3d angularForce = PhysicsUtils.odeVecToJomlVec(body.getTorque()); + if(position.distance(lastSentPosition) > UPDATE_THRESHOLD || 1.0 - rotation.dot(lastSentRotation) > UPDATE_THRESHOLD){ + lastSentPosition.set(position); + lastSentRotation.set(rotation); + DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage( + EntityMessage.constructsyncPhysicsMessage( + parent.getId(), + Globals.timekeeper.getNumberOfSimFramesElapsed(), + position.x, + position.y, + position.z, + rotation.x, + rotation.y, + rotation.z, + rotation.w, + linearVel.x, + linearVel.y, + linearVel.z, + angularVel.x, + angularVel.y, + angularVel.z, + linearForce.x, + linearForce.y, + linearForce.z, + angularForce.x, + angularForce.y, + angularForce.z + ) + ); + } } } @@ -106,6 +111,7 @@ public class ServerPhysicsSyncTree implements BehaviorTree { * @param tree The behavior tree to detach */ public static void detachTree(Entity entity, BehaviorTree tree){ + ServerBehaviorTreeUtils.detatchBTreeFromEntity(entity, tree); } /** diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index 98d443f4..7e95f337 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -431,7 +431,7 @@ public class ItemUtils { if(item.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && item.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ //destroy physics //this deregisters from all four & unhooks rigid bodies from the physics runtime - Globals.clientSceneWrapper.getCollisionEngine().destroyEntityThatHasPhysics(item); + Globals.clientSceneWrapper.getCollisionEngine().destroyPhysics(item); //destroy hitboxes HitboxCollectionState.destroyHitboxState(item); //destroy graphics diff --git a/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java b/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java index 21be474f..c8464583 100644 --- a/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java +++ b/src/main/java/electrosphere/server/datacell/physics/PhysicsDataCell.java @@ -91,7 +91,7 @@ public class PhysicsDataCell { */ public void destroyPhysics(){ Realm realm = Globals.realmManager.getEntityRealm(physicsEntity); - realm.getCollisionEngine().destroyEntityThatHasPhysics(physicsEntity); + realm.getCollisionEngine().destroyPhysics(physicsEntity); } /** diff --git a/src/main/java/electrosphere/server/datacell/utils/ServerBehaviorTreeUtils.java b/src/main/java/electrosphere/server/datacell/utils/ServerBehaviorTreeUtils.java index d8e0f336..981fd41c 100644 --- a/src/main/java/electrosphere/server/datacell/utils/ServerBehaviorTreeUtils.java +++ b/src/main/java/electrosphere/server/datacell/utils/ServerBehaviorTreeUtils.java @@ -61,7 +61,7 @@ public class ServerBehaviorTreeUtils { entityBTreeMap.get(entity).remove(behaviorTree); //deregister from cell ServerDataCell currentCell = DataCellSearchUtils.getEntityDataCell(entity); - currentCell.getScene().registerBehaviorTree(behaviorTree); + currentCell.getScene().deregisterBehaviorTree(behaviorTree); }