View Javadoc

1   /*
2    * Entreri, an entity-component framework in Java
3    *
4    * Copyright (c) 2013, Michael Ludwig
5    * All rights reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without modification,
8    * are permitted provided that the following conditions are met:
9    *
10   *     Redistributions of source code must retain the above copyright notice,
11   *         this list of conditions and the following disclaimer.
12   *     Redistributions in binary form must reproduce the above copyright notice,
13   *         this list of conditions and the following disclaimer in the
14   *         documentation and/or other materials provided with the distribution.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
20   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package com.lhkbob.entreri;
28  
29  import com.lhkbob.entreri.impl.EntitySystemImpl;
30  import com.lhkbob.entreri.property.Property;
31  import com.lhkbob.entreri.property.PropertyFactory;
32  import com.lhkbob.entreri.task.Scheduler;
33  import com.lhkbob.entreri.task.Task;
34  
35  import java.util.Collection;
36  import java.util.Iterator;
37  
38  /**
39   * <p/>
40   * EntitySystem is the main container for the entities within a logical system such as a
41   * game or physics world. It contains all entities needed for processing the scene or
42   * data. Entities are created with {@link #addEntity()} or {@link #addEntity(Entity)}.
43   * They can be removed (and effectively destroyed) with {@link #removeEntity(Entity)}.
44   * <p/>
45   * After an Entity is created, Components can be added to it to store domain-specific data
46   * and configure its behaviors. The specifics of the data and behavior depends on the
47   * Component implementations and Tasks used to process your data.
48   * <p/>
49   * The {@link Scheduler} of an EntitySystem can be used to create {@link
50   * com.lhkbob.entreri.task.Job Jobs} composed of {@link Task Tasks} that will process the
51   * entities within an entity system in an organized fashion. Generally, the processing of
52   * all controllers through their different phases constitutes a complete "frame".
53   * <p/>
54   * When Entities are created by an EntitySystem, the created instance is assigned an ID
55   * which represents its true identity.
56   * <p/>
57   * Use {@link Factory#create()} to get a new instance of an EntitySystem.
58   *
59   * @author Michael Ludwig
60   * @see Entity
61   * @see Component
62   */
63  public interface EntitySystem extends Iterable<Entity> {
64      public static class Factory {
65          /**
66           * Create a new EntitySystem using the default implementation with entreri
67           *
68           * @return A new, empty EntitySystem
69           */
70          public static EntitySystem create() {
71              return new EntitySystemImpl();
72          }
73      }
74  
75      /**
76       * Get all Component types within this EntitySystem that have types assignable to the
77       * input <var>type</var>.
78       *
79       * @param type The query type
80       *
81       * @return All Component interfaces that have components in this EntitySystem that are
82       *         subclasses of the input component data type
83       *
84       * @throws NullPointerException if type is null
85       */
86      public <T extends Component> Collection<Class<? extends T>> getComponentTypes(
87              Class<T> type);
88  
89      /**
90       * Get all Component interfaces currently used by the EntitySystem. If a type has had
91       * all of its components removed, it will still be returned here.
92       *
93       * @return All TypeIds at one point used by this system
94       */
95      public Collection<Class<? extends Component>> getComponentTypes();
96  
97      /**
98       * Return the Scheduler for this EntitySystem that can be used to organize processing
99       * of the system using {@link Task} implementations.
100      *
101      * @return The Scheduler for this system
102      */
103     public Scheduler getScheduler();
104 
105     /**
106      * Return an iterator over all of the entities within the system. The returned
107      * iterator's remove() method will remove the entity from the system with behavior
108      * identical to calling {@link #removeEntity(Entity)}.
109      *
110      * @return An iterator over the entities of the system
111      */
112     @Override
113     public Iterator<Entity> iterator();
114 
115     /**
116      * Return an iterator over all components of with the given type. The returned
117      * iterator uses a single flyweight Component instance of T, so it is a fast iterator.
118      * This effectively wraps a {@link ComponentIterator} in a standard {@link Iterator}
119      * with a single required component type.
120      *
121      * @param type The type of component to iterate over
122      *
123      * @return A fast iterator over components in this system
124      */
125     public <T extends Component> Iterator<T> iterator(Class<T> type);
126 
127     /**
128      * Return a new ComponentIterator that must be configured with required and optional
129      * components before use.
130      *
131      * @return A new iterator over the components in this system
132      */
133     public ComponentIterator fastIterator();
134 
135     /**
136      * <p/>
137      * Compact the entity and component data so that iteration is more efficient. In the
138      * life time of an entity system, entities and components are added and removed,
139      * possibly causing the list of components for a given type to be in a different order
140      * than the list of entities. This is due to implementation details needed to make
141      * additions and removals constant time.
142      * <p/>
143      * Invoking compact() after a large number of additions or removals to the system is a
144      * good idea. Alternatively, invoking it every few frames in a game works as well. An
145      * entity system that has no additions or removals of entities (or their components)
146      * gains no benefit from compacting, except potentially freeing excess memory.
147      * <p/>
148      * Compacting is not overly fast or slow, so it should not cause noticeably drops in
149      * frame rate. As an example, on a test system with 20,000 entities compact() took
150      * ~2ms on an Intel i5 processor. Of course, mileage may very.
151      */
152     public void compact();
153 
154     /**
155      * Add a new Entity to this EntitySystem. The created Entity will not have any
156      * attached Components. You can create a new entity from a template by calling {@link
157      * #addEntity(Entity)}.
158      *
159      * @return A new Entity in the system, without any components
160      */
161     public Entity addEntity();
162 
163     /**
164      * <p/>
165      * Add a new Entity to this EntitySystem. If <var>template</var> is not null, the
166      * components attached to the template will have their state cloned onto the new
167      * entity. The semantics of cloning is defined by {@link com.lhkbob.entreri.property.PropertyFactory#clone(com.lhkbob.entreri.property.Property,
168      * int, com.lhkbob.entreri.property.Property, int)}, but by default it follows Java's
169      * reference/value rule.
170      * <p/>
171      * Specifying a null template makes this behave identically to {@link #addEntity()}.
172      *
173      * @param template The template to clone
174      *
175      * @return A new Entity in the system with the same component state as the template
176      *
177      * @throws IllegalStateException if the template is not a live entity
178      */
179     public Entity addEntity(Entity template);
180 
181     /**
182      * <p/>
183      * Remove the given entity from this system. The entity and its attached components
184      * are removed from the system. This will cause the entity and its components to no
185      * longer be alive. Any ComponentData's referencing the entity's components will
186      * become invalid until assigned to a new component.
187      * <p/>
188      * When an entity is removed, it will set its owner to null, and disown all of its
189      * owned objects. If any of those owned objects are entities or components, they are
190      * removed from the system as well.
191      *
192      * @param e The entity to remove
193      *
194      * @throws NullPointerException     if e is null
195      * @throws IllegalArgumentException if the entity was not created by this system, or
196      *                                  already removed
197      */
198     public void removeEntity(Entity e);
199 
200     /**
201      * <p/>
202      * Dynamically update the available properties of the given Component type by adding a
203      * Property created by the given PropertyFactory. The property will be managed by the
204      * system as if it was a declared property of the component type.
205      * <p/>
206      * All components, current and new, will initially have their starting values for the
207      * decorated property be the default as defined by the factory. The returned property
208      * can be accessed and used by Tasks to add dynamic runtime data to statically defined
209      * component types.
210      *
211      * @param <P>     The created property type
212      * @param type    The component type to mutate
213      * @param factory The property factory that creates the decorating property
214      *
215      * @return The property that has decorated the given component type
216      *
217      * @throws NullPointerException if type or factory are null
218      */
219     public <T extends Component, P extends Property> P decorate(Class<T> type,
220                                                                 PropertyFactory<P> factory);
221 }