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 }