All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artemis.World Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
package com.artemis;

import com.artemis.injection.CachedInjector;
import com.artemis.injection.Injector;
import com.artemis.utils.Bag;
import com.artemis.utils.ImmutableBag;
import com.artemis.utils.IntBag;

import java.util.*;

import static com.artemis.WorldConfiguration.ASPECT_SUBSCRIPTION_MANAGER_IDX;
import static com.artemis.WorldConfiguration.COMPONENT_MANAGER_IDX;
import static com.artemis.WorldConfiguration.ENTITY_MANAGER_IDX;

/**
 * The primary instance for the framework.
 * 

* It contains all the systems. You must use this to create, delete and * retrieve entities. It is also important to set the delta each game loop * iteration, and initialize before game loop. *

* @author Arni Arent * @author junkdog */ public class World { /** Manages all entities for the world. */ private final EntityManager em; /** Manages all component-entity associations for the world. */ private final ComponentManager cm; /** Pool of entity edits. */ final BatchChangeProcessor batchProcessor; /** Contains all systems unordered. */ final Bag systemsBag; /** Manages all aspect based entity subscriptions for the world. */ final AspectSubscriptionManager asm; /** Contains strategy for invoking systems upon process. */ SystemInvocationStrategy invocationStrategy; final WorldSegment partition; /** The time passed since the last update. */ public float delta; /** * Creates a world without custom systems. *

* {@link com.artemis.EntityManager}, {@link ComponentManager} and {@link AspectSubscriptionManager} are * available by default. *

* Why are you using this? Use {@link #World(WorldConfiguration)} to create a world with your own systems. */ public World() { this(new WorldConfiguration()); } /** * Creates a new world. *

* {@link com.artemis.EntityManager}, {@link ComponentManager} and {@link AspectSubscriptionManager} are * available by default, on top of your own systems. *

* @see WorldConfigurationBuilder * @see WorldConfiguration */ public World(WorldConfiguration configuration) { partition = new WorldSegment(configuration); systemsBag = configuration.systems; final ComponentManager lcm = (ComponentManager) systemsBag.get(COMPONENT_MANAGER_IDX); final EntityManager lem = (EntityManager) systemsBag.get(ENTITY_MANAGER_IDX); final AspectSubscriptionManager lasm = (AspectSubscriptionManager) systemsBag.get(ASPECT_SUBSCRIPTION_MANAGER_IDX); cm = lcm == null ? new ComponentManager(configuration.expectedEntityCount()) : lcm; em = lem == null ? new EntityManager(configuration.expectedEntityCount()) : lem; asm = lasm == null ? new AspectSubscriptionManager() : lasm; batchProcessor = new BatchChangeProcessor(this); configuration.initialize(this, partition.injector, asm); } /** * Inject dependencies on object. *

* Immediately perform dependency injection on the target, even if the target isn't of an Artemis class. *

* If you want to specify nonstandard dependencies to inject, use * {@link com.artemis.WorldConfiguration#register(String, Object)} instead, or * configure an {@link com.artemis.injection.Injector} *

* If you want a non-throwing alternative, use {@link #inject(Object, boolean)} * @param target * Object to inject into. * throws {@link MundaneWireException} if {@code target} is annotated with {@link com.artemis.annotations.SkipWire} * @see com.artemis.annotations.Wire for more details about dependency injection. * @see #inject(Object, boolean) */ public void inject(Object target) { inject(target, true); } /** * Inject dependencies on object. *

* Will not if it is annotated with {@link com.artemis.annotations.Wire}. *

* If you want to specify nonstandard dependencies to inject, use * {@link com.artemis.WorldConfiguration#register(String, Object)} instead, or * configure an {@link com.artemis.injection.Injector}. * @param target * Object to inject into. * @param failIfNotInjectable * if true, this method will * throws {@link MundaneWireException} if {@code target} is annotated with * {@link com.artemis.annotations.SkipWire} and {@code failIfNotInjectable} is true * @see com.artemis.annotations.Wire for more details about dependency injection. * @see #inject(Object) */ public void inject(Object target, boolean failIfNotInjectable) { boolean injectable = partition.injector.isInjectable(target); if (!injectable && failIfNotInjectable) throw new MundaneWireException("Attempted injection on " + target.getClass() .getName() + ", which is annotated with @SkipWire"); if (injectable) partition.injector.inject(target); } public T getRegistered(String name) { return partition.injector.getRegistered(name); } public T getRegistered(Class type) { return partition.injector.getRegistered(type); } /** * Disposes all systems. Only necessary if either need to free * managed resources upon bringing the world to an end. * @throws ArtemisMultiException * if any system throws an exception. */ public void dispose() { List exceptions = new ArrayList(); for (BaseSystem system : systemsBag) { try { system.dispose(); } catch (Exception e) { exceptions.add(e); } } if (exceptions.size() > 0) throw new ArtemisMultiException(exceptions); } /** * Get entity editor for entity. * @return a fast albeit verbose editor to perform batch changes to entities. * @param entityId entity to fetch editor for. */ public EntityEdit edit(int entityId) { if (!em.isActive(entityId)) throw new RuntimeException("Issued edit on deleted " + entityId); return batchProcessor.obtainEditor(entityId); } /** * Gets the composition id uniquely identifying the * component composition of an entity. Each composition identity maps * to one unique BitVector. * * @param entityId Entity for which to get the composition id * @return composition identity of entity */ public int compositionId(int entityId) { return cm.getIdentity(entityId); } /** * Returns a manager that takes care of all the entities in the world. * @return entity manager */ public EntityManager getEntityManager() { return em; } /** * Returns a manager that takes care of all the components in the world. * @return component manager */ public ComponentManager getComponentManager() { return cm; } /** * Returns the manager responsible for creating and maintaining * {@link EntitySubscription subscriptions} in the world. * * @return aspect subscription manager */ public AspectSubscriptionManager getAspectSubscriptionManager() { return asm; } /** * Time since last game loop. * @return delta time since last game loop */ public float getDelta() { return delta; } /** * You must specify the delta for the game here. * @param delta * time since last game loop */ public void setDelta(float delta) { this.delta = delta; } /** * Delete the entity from the world. * @param e * the entity to delete * @see #delete(int) recommended alternative. */ public void deleteEntity(Entity e) { delete(e.id); } /** * Delete the entity from the world. * * The entity is considered to be in a final state once invoked; * adding or removing components from an entity scheduled for * deletion will likely throw exceptions. * * @param entityId * the entity to delete */ public void delete(int entityId) { batchProcessor.delete(entityId); } /** * Create and return a new or reused entity instance. Entity is * automatically added to the world. * * @return entity * @see #create() recommended alternative. */ public Entity createEntity() { Entity e = em.createEntityInstance(); batchProcessor.changed.unsafeSet(e.getId()); return e; } /** * Create and return a new or reused entity id. Entity is * automatically added to the world. * * @return assigned entity id, where id >= 0. */ public int create() { int entityId = em.create(); batchProcessor.changed.unsafeSet(entityId); return entityId; } /** * Create and return an {@link Entity} wrapping a new or reused entity instance. * Entity is automatically added to the world. * * Use {@link Entity#edit()} to set up your newly created entity. * * You can also create entities using: *

    *
  • {@link com.artemis.utils.EntityBuilder} Convenient entity creation. Not useful when pooling.
  • *
  • {@link com.artemis.Archetype} Fastest, low level, no parameterized components.
  • *
  • Serialization, * with a simple prefab-like class to parameterize the entities.
  • *
* * @see #create() recommended alternative. * @return entity */ public Entity createEntity(Archetype archetype) { Entity e = em.createEntityInstance(); int id = e.getId(); archetype.transmuter.perform(id); cm.setIdentity(e.id, archetype.compositionId); batchProcessor.changed.unsafeSet(id); return e; } /** * Create and return an {@link Entity} wrapping a new or reused entity instance. * Entity is automatically added to the world. * * Use {@link Entity#edit()} to set up your newly created entity. * * You can also create entities using: * - {@link com.artemis.utils.EntityBuilder} Convenient entity creation. Not useful when pooling. * - {@link com.artemis.Archetype} Fastest, low level, no parameterized components. * * @return assigned entity id */ public int create(Archetype archetype) { int entityId = em.create(); archetype.transmuter.perform(entityId); cm.setIdentity(entityId, archetype.compositionId); batchProcessor.changed.unsafeSet(entityId); return entityId; } /** * Get entity with the specified id. * * Resolves entity id to the unique entity instance. This method may * return an entity even if it isn't active in the world. Make sure to * not retain id's of deleted entities. * * @param entityId * the entities id * @return the specific entity */ public Entity getEntity(int entityId) { return em.getEntity(entityId); } /** * Gives you all the systems in this world for possible iteration. * @return all entity systems in world */ public ImmutableBag getSystems() { return systemsBag; } /** * Retrieve a system for specified system type. * @param * the class type of system * @param type * type of system * @return instance of the system in this world */ @SuppressWarnings("unchecked") public T getSystem(Class type) { return (T) partition.systems.get(type); } /** Set strategy for invoking systems on {@link #process()}. */ protected void setInvocationStrategy(SystemInvocationStrategy invocationStrategy) { this.invocationStrategy = invocationStrategy; invocationStrategy.setWorld(this); invocationStrategy.setSystems(systemsBag); invocationStrategy.initialize(); } /** * Process all non-passive systems. * @see InvocationStrategy to control and extend how systems are invoked. */ public void process() { invocationStrategy.process(); IntBag pendingPurge = batchProcessor.getPendingPurge(); if (!pendingPurge.isEmpty()) { cm.clean(pendingPurge); em.clean(pendingPurge); batchProcessor.purgeComponents(); } } /** * Retrieves a ComponentMapper instance for fast retrieval of components * from entities. * * Odb automatically injects component mappers into systems, calling this * method is usually not required., * * @param * class type of the component * @param type * type of component to get mapper for * @return mapper for specified component type */ public ComponentMapper getMapper(Class type) { return cm.getMapper(type); } /** * @return Injector responsible for dependency injection. */ public Injector getInjector() { return partition.injector; } /** * @return Strategy used for invoking systems during {@link World#process()}. */ public T getInvocationStrategy() { return (T) invocationStrategy; } static class WorldSegment { /** Contains all systems and systems classes mapped. */ final Map, BaseSystem> systems; /** Responsible for dependency injection. */ final Injector injector; WorldSegment(WorldConfiguration configuration) { systems = new IdentityHashMap, BaseSystem>(); injector = (configuration.injector != null) ? configuration.injector : new CachedInjector(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy