package electrosphere.entity.scene; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityTags; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.state.attach.AttachUtils; import electrosphere.logger.LoggerInterface; import electrosphere.util.annotation.Exclude; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; /** * A game scene */ public class Scene { /** * The map of id -> entity */ Map entityIdMap; /** * The map of tag -> set of entities corresponding to that tag */ Map> tagEntityMap; /** * The list of behavior trees */ List behaviorTreeList; @Exclude /** * Lock for threadsafeing the scene */ ReentrantLock lock = new ReentrantLock(); /** * Constructor */ public Scene(){ entityIdMap = new HashMap(); tagEntityMap = new HashMap>(); behaviorTreeList = new LinkedList(); tagEntityMap.put(EntityTags.BONE_ATTACHED, new HashSet()); tagEntityMap.put(EntityTags.COLLIDABLE, new HashSet()); tagEntityMap.put(EntityTags.SPRINTABLE, new HashSet()); tagEntityMap.put(EntityTags.MOVEABLE, new HashSet()); tagEntityMap.put(EntityTags.ATTACKER, new HashSet()); tagEntityMap.put(EntityTags.TARGETABLE, new HashSet()); tagEntityMap.put(EntityTags.LIFE_STATE, new HashSet()); tagEntityMap.put(EntityTags.CREATURE, new HashSet()); tagEntityMap.put(EntityTags.UI, new HashSet()); tagEntityMap.put(EntityTags.DRAWABLE, new HashSet()); tagEntityMap.put(EntityTags.DRAW_INSTANCED, new HashSet()); tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_SOLIDS_PASS, new HashSet()); tagEntityMap.put(EntityTags.DRAW_VOLUMETIC_DEPTH_PASS, new HashSet()); tagEntityMap.put(EntityTags.DRAW_CAST_SHADOW, new HashSet()); tagEntityMap.put(EntityTags.LIGHT, new HashSet()); tagEntityMap.put(EntityTags.ITEM, new HashSet()); tagEntityMap.put(EntityTags.GRAVITY, new HashSet()); tagEntityMap.put(EntityTags.PARTICLE, new HashSet()); tagEntityMap.put(EntityTags.TRANSFORM_ATTACHED, new HashSet()); } /** * Registers an entity to the scene * @param e The entity to register */ public void registerEntity(Entity e){ lock.lock(); entityIdMap.put(e.getId(), e); lock.unlock(); } /** * Registers an entity to a given tag * @param e The entity * @param tag The tag */ public void registerEntityToTag(Entity e, String tag){ lock.lock(); if(tagEntityMap.containsKey(tag)){ tagEntityMap.get(tag).add(e); } else { Set newEntityList = new HashSet(); newEntityList.add(e); tagEntityMap.put(tag,newEntityList); } lock.unlock(); } /** * Gets all entities registered to a tag * @param tag The tag * @return A list of all entities with the tag, or null if no entities have been added to the tag yet */ public Set getEntitiesWithTag(String tag){ lock.lock(); Set rVal = null; if(tagEntityMap.containsKey(tag)){ rVal = new HashSet(tagEntityMap.get(tag)); } lock.unlock(); return rVal; } /** * Removes an entity from a tag * @param e The entity * @param tag The tag */ public void removeEntityFromTag(Entity e, String tag){ lock.lock(); tagEntityMap.get(tag).remove(e); lock.unlock(); } /** * Deregisters an entity from an entity manager * @param e */ public void deregisterEntity(Entity e){ lock.lock(); for(String key : tagEntityMap.keySet()){ tagEntityMap.get(key).remove(e); } entityIdMap.remove(e.getId()); lock.unlock(); } /** * Recursively deregisters an entity and all entities attached via AttachUtils * @param target The top level entity to deregister */ public void recursiveDeregister(Entity target){ lock.lock(); if(AttachUtils.hasChildren(target)){ List childrenList = AttachUtils.getChildrenList(target); for(Entity currentChild : childrenList){ this.recursiveDeregister(currentChild); } } this.deregisterEntity(target); lock.unlock(); } /** * Gets an entity via its ID * @param id The id to search for * @return The entity with that ID */ public Entity getEntityFromId(int id){ lock.lock(); Entity rVal = (Entity)entityIdMap.get(id); lock.unlock(); return rVal; } /** * Checks if a scene contains a given entity * @param e The entity * @return true if the scene contains the entity, false otherwise */ public boolean containsEntity(Entity e){ lock.lock(); boolean rVal = entityIdMap.containsKey(e.getId()); lock.unlock(); return rVal; } /** * Registers a behavior tree to simulate each scene simulation frame * @param tree The behavior tree to register */ public void registerBehaviorTree(BehaviorTree tree){ lock.lock(); behaviorTreeList.add(tree); lock.unlock(); } /** * Registers a new behavior tree that executes a task * @param task The task */ public void registerBehaviorTree(Runnable task){ lock.lock(); this.registerBehaviorTree(new BehaviorTree(){public void simulate(float deltaTime) { task.run(); }}); lock.unlock(); } /** * Deregisters a behavior tree from the scene * @param tree The behavior tree to deregister */ public void deregisterBehaviorTree(BehaviorTree tree){ lock.lock(); while(behaviorTreeList.contains(tree)){ behaviorTreeList.remove(tree); } lock.unlock(); } /** * Simulates all behavior trees stored in the entity manager */ public void simulateBehaviorTrees(float deltaTime){ lock.lock(); Globals.profiler.beginAggregateCpuSample("Scene.simulateBehaviorTrees"); List trees = new LinkedList(behaviorTreeList); for(BehaviorTree tree : trees){ tree.simulate(deltaTime); } Globals.profiler.endCpuSample(); lock.unlock(); } /** * Gets the collection of all entities in the scene * @return The collection of all entities in the scene */ public Collection getEntityList(){ lock.lock(); Collection rVal = new LinkedList(this.entityIdMap.values()); lock.unlock(); return rVal; } /** * Gets the list of behavior trees attached to the scene * @return The list of behavior trees attached to the scene */ public Collection getBehaviorTrees(){ lock.lock(); Collection rVal = new LinkedList(this.behaviorTreeList); lock.unlock(); return rVal; } /** * Describes the scene in log messages */ public void describeScene(){ LoggerInterface.loggerEngine.WARNING("Entities present in scene:"); for(Entity entity : this.entityIdMap.values()){ LoggerInterface.loggerEngine.WARNING(entity.getId() + ""); } } }