package electrosphere.entity; import org.joml.Vector3d; import electrosphere.engine.Globals; import electrosphere.entity.state.hitbox.HitboxCollectionState; import electrosphere.entity.types.collision.CollisionObjUtils; import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.ServerDataCell; import electrosphere.server.datacell.utils.DataCellSearchUtils; import electrosphere.server.datacell.utils.EntityLookupUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; /** * Entity utilities specifically for the server side */ public class ServerEntityUtils { /** * Called when the creature is first spawned to serialize to all people in its initial chunk. *

* !!NOTE!!: This function must be called after the entity has fully been created. * The initializeServerSideEntity logic requires knowing the type of entity (creature, foliage, etc) * which is typically set further in the function than the initial "spawnServerEntity" that returns * the actual Entity() object. *

* @param entity * @param position */ public static void initiallyPositionEntity(Realm realm, Entity entity, Vector3d position){ //reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called CollisionObjUtils.serverPositionCharacter(entity, position); //get current server data cell ServerDataCell cell = realm.getDataCellManager().getDataCellAtPoint(position); if(cell != null){ //initialize server datacell tracking of this entity realm.initializeServerSideEntity(entity, cell); } else { //if it doesn't already exist, try creating it and if successfull move creature cell = realm.getDataCellManager().tryCreateCellAtPoint(position); //initialize server datacell tracking of this entity realm.initializeServerSideEntity(entity, cell); } } /** * Called to reposition the creature * @param entity * @param position */ public static void repositionEntity(Entity entity, Vector3d position){ Realm realm = Globals.realmManager.getEntityRealm(entity); //if server, get current server data cell ServerDataCell oldDataCell = realm.getDataCellManager().getDataCellAtPoint(EntityUtils.getPosition(entity)); ServerDataCell newDataCell = realm.getDataCellManager().getDataCellAtPoint(position); if(oldDataCell != newDataCell){ if(newDataCell != null){ ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell); ServerBehaviorTreeUtils.updateCell(entity, oldDataCell); } else { //if it doesn't already exist, try creating it and if successfull move creature newDataCell = realm.getDataCellManager().tryCreateCellAtPoint(EntityUtils.getPosition(entity)); if(newDataCell != null){ ServerDataCell.moveEntityFromCellToCell(entity, oldDataCell, newDataCell); ServerBehaviorTreeUtils.updateCell(entity, oldDataCell); } } } // //if the server is also a client, update the drawcell manager to know to pull new chunks // if(Globals.RUN_CLIENT){ // Globals.drawCellManager.invalidateAllCells(); // Globals.drawCellManager.setCellX(Globals.clientPlayerData.getWorldPos().x); // Globals.drawCellManager.setCellY(Globals.clientPlayerData.getWorldPos().z); // } //reposition entity CollisionObjUtils.serverPositionCharacter(entity, position); } /** * Destroys an entity on the server * @param entity the entity to destroy */ public static void destroyEntity(Entity entity){ ServerDataCell cell = DataCellSearchUtils.getEntityDataCell(entity); Realm realm = Globals.realmManager.getEntityRealm(entity); if(cell != null){ cell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(entity.getId())); //if the entity had physics, remove them from the world realm.getCollisionEngine().destroyEntityThatHasPhysics(entity); } HitboxCollectionState.destroyHitboxState(entity); ServerBehaviorTreeUtils.deregisterEntity(entity); Globals.realmManager.removeEntity(entity); EntityLookupUtils.removeEntity(entity); //deregister all behavior trees EntityUtils.cleanUpEntity(entity); } /** * Guarantees that the returned position is in bounds of the server realm * @param realm The realm to test * @param position the position * @return Either the position if it is in bounds, or the closest position that is in bounds */ public static Vector3d guaranteePositionIsInBounds(Realm realm, Vector3d position){ return realm.getDataCellManager().guaranteePositionIsInBounds(position); } }