package electrosphere.client.scene; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.joml.Vector3d; import org.ode4j.ode.DContactGeom; import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine.CollisionResolutionCallback; import electrosphere.collision.collidable.Collidable; import electrosphere.collision.hitbox.HitboxManager; import electrosphere.collision.hitbox.HitboxUtils; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.Scene; import electrosphere.logger.LoggerInterface; /** * Wrapper around the scene object to provide lots of much needed client-specific utility * Does all the server<->client id translation and provides utilities to map between the two */ public class ClientSceneWrapper { //entity id translation between server/client Map clientToServerIdMap = new ConcurrentHashMap(); Map serverToClientIdMap = new ConcurrentHashMap(); //The scene backing the wrapper Scene scene; //The engine used to back physics collision checks in client CollisionEngine collisionEngine; //The hitbox manager HitboxManager hitboxManager; /** * Constructor * @param scene The scene * @param collisionEngine The collision engine */ public ClientSceneWrapper(Scene scene, CollisionEngine collisionEngine){ this.scene = scene; this.collisionEngine = collisionEngine; this.hitboxManager = new HitboxManager(resolutionCallback); } /** * Registers a server provided ID as a mapping to a given ID on the client * @param clientId The client's generated ID * @param serverId The server's provided ID */ public void mapIdToId(int clientId, int serverId){ LoggerInterface.loggerEngine.DEBUG("MapID: " + clientId + " <===> " + serverId); clientToServerIdMap.put(clientId, serverId); serverToClientIdMap.put(serverId, clientId); } /** * Resolves a client ID to the equivalent ID on the server * @param clientId The id provided by the client * @return The equivalent id on the server */ public int mapClientToServerId(int clientId){ return clientToServerIdMap.get(clientId); } /** * Translates the id provided by the server into the equivalent id on the client * @param serverId The id provided by the server * @return The equivalent id on the client */ public int mapServerToClientId(int serverId){ return serverToClientIdMap.get(serverId); } /** * Checks if the scene wrapper contains the provided server id * @param serverId The server id * @return true if the map contains that id, false otherwise */ public boolean containsServerId(int serverId){ return serverToClientIdMap.containsKey(serverId); } /** * Returns true if the server->client map contains a given id * @param id The id to search for * @return True if the server->client map contains the provided id */ public boolean serverToClientMapContainsId(int id){ return serverToClientIdMap.containsKey(id); } /** * Gets the entity provided a server-provided id * @param id The server-provided ID * @return The entity in question */ public Entity getEntityFromServerId(int id){ return scene.getEntityFromId(mapServerToClientId(id)); } /** * Gets the scene backing this client scene wrapper * @return The scene */ public Scene getScene(){ return this.scene; } /** * Gets the collision engine backing the wrapper * @return */ public CollisionEngine getCollisionEngine(){ return collisionEngine; } /** * Gets the hitbox manager for the client * @return The hitbox manager */ public HitboxManager getHitboxManager(){ return hitboxManager; } /** * Destroys all entities outside simulation range */ public void destroyEntitiesOutsideSimRange(){ Globals.profiler.beginCpuSample("destroyEntitiesOutsideSimRange"); // if(Globals.drawCellManager != null && Globals.playerEntity != null){ // double cullRadius = Globals.drawCellManager.getDrawRadius() + ServerTerrainChunk.CHUNK_DIMENSION; // Vector3d playerPosition = EntityUtils.getPosition(Globals.playerEntity); // List entityList = scene.getEntityList(); // for(Entity entity : entityList){ // Vector3d position = EntityUtils.getPosition(entity); // if(playerPosition.distance(position) > cullRadius){ // EntityUtils.cleanUpEntity(entity); // } // } // } Globals.profiler.endCpuSample(); } /** * The resolution callback that is invoked once a collision has occurred */ CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() { @Override public void resolve(DContactGeom geom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) { HitboxUtils.clientDamageHitboxColision(impactor.getParent(), receiver.getParent()); } }; }