package electrosphere.server.datacell; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import org.joml.Vector3d; import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionWorldData; import electrosphere.collision.hitbox.HitboxManager; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.game.server.world.ServerWorldData; import electrosphere.net.server.player.Player; import electrosphere.server.chemistry.ServerChemistryCollisionCallback; import electrosphere.server.collision.ServerHitboxResolutionCallback; import electrosphere.server.content.ServerContentManager; /** * Manages all realms for the engine. Should be a singleton */ public class RealmManager { //All realms in this manager Set realms = new CopyOnWriteArraySet(); //Map of entities to the realm the entity is in Map entityToRealmMap = new ConcurrentHashMap(); //Map of player to the realm the player is in Map playerToRealmMap = new ConcurrentHashMap(); /** * Constructor */ public RealmManager(){ } /** * Creates a realm * @return The realm */ public Realm createRealm(){ //create chemistry engine CollisionEngine chemistryEngine = new CollisionEngine(); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); return new Realm( new ServerWorldData(), new CollisionEngine(), chemistryEngine, new HitboxManager(new ServerHitboxResolutionCallback()), ServerContentManager.createServerContentManager(false) ); } /** * Creates a realm that uses a gridded layout (ie an array of cells in 3d space) * @return The realm */ public Realm createGriddedRealm(ServerWorldData serverWorldData, ServerContentManager serverContentManager){ //create collision engine CollisionEngine collisionEngine = new CollisionEngine(); collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); //create chemistry engine CollisionEngine chemistryEngine = new CollisionEngine(); chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); //create realm Realm realm = new Realm( serverWorldData, collisionEngine, chemistryEngine, new HitboxManager(new ServerHitboxResolutionCallback()), serverContentManager ); //create function classes GriddedDataCellManager griddedDataCellManager = new GriddedDataCellManager(realm); //add function classes to realm realm.setDataCellManager(griddedDataCellManager); //register within the manager realms.add(realm); return realm; } /** * Creates a viewport realm * @return The viewport realm */ public Realm createViewportRealm(Vector3d minPoint, Vector3d maxPoint){ //create the server world data ServerWorldData serverWorldData = ServerWorldData.createFixedWorldData(minPoint, maxPoint); //create collision engine CollisionEngine collisionEngine = new CollisionEngine(); collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); //create chemistry engine CollisionEngine chemistryEngine = new CollisionEngine(); chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); //create realm Realm realm = new Realm( serverWorldData, collisionEngine, chemistryEngine, new HitboxManager(new ServerHitboxResolutionCallback()), ServerContentManager.createServerContentManager(false) ); //add function classes to realm realm.setDataCellManager(ViewportDataCellManager.create(realm)); //register realms.add(realm); return realm; } /** * Maps an entity to a realm * @param entity The entity * @param realm The realm */ public void mapEntityToRealm(Entity entity, Realm realm){ entityToRealmMap.put(entity, realm); } /** * Removes the entity from tracking in this realm manager * @param entity The entity to remove */ public void removeEntity(Entity entity){ entityToRealmMap.remove(entity); } /** * Gets the realm an entity is inside of * @param entity The entity * @return The realm, or null if the entity is not inside a realm */ public Realm getEntityRealm(Entity entity){ return entityToRealmMap.get(entity); } /** * Gets the set containing all realms in the manager * @return The set containing all realms in the manager */ public Set getRealms(){ return realms; } /** * Simulates all realms in this manager */ public void simulate(){ Globals.profiler.beginCpuSample("RealmManager.simulate"); for(Realm realm : realms){ realm.simulate(); } Globals.profiler.endCpuSample(); } //TODO: !!URGENT!! come up with some mechanism to enforce this actually being called every time a player is added to a server data cell /** * Adds a player to a realm * @param player The player * @param realm The realm */ public void setPlayerRealm(Player player, Realm realm){ playerToRealmMap.put(player, realm); } /** * Gets the realm of a given player * @param player The player * @return The realm */ public Realm getPlayerRealm(Player player){ return playerToRealmMap.get(player); } /** * Saves all cells in all realms in the realm manager * @param saveName The name of the save */ public void save(String saveName){ for(Realm realm : realms){ realm.save(saveName); } } /** * Returns the first realm in the manager * @return The first realm in the manager */ public Realm first(){ if(realms.size() == 0){ return null; } return realms.iterator().next(); } /** * Resets the realm manager */ public void reset(){ this.realms.clear(); this.entityToRealmMap.clear(); this.playerToRealmMap.clear(); } /** * Closes the realm manager, destroying all resources */ public void close(){ for(Realm realm : this.realms){ if(realm.getServerWorldData() != null && realm.getServerWorldData().getServerTerrainManager() != null){ realm.getServerWorldData().getServerTerrainManager().closeThreads(); } } this.reset(); } }