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 }