package net.onedaybeard.dominatrix.artemis; import net.onedaybeard.dominatrix.artemis.JsonComponentFactory.FactoryInstance; import net.onedaybeard.dominatrix.util.Logger; import com.artemis.Component; import com.artemis.ComponentMapper; import com.artemis.Entity; import com.artemis.Manager; import com.artemis.World; import com.artemis.managers.TagManager; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.Array; /** * Artemis manager for creating entities defined in json data files. * * @see EntityFactoryManager#addNewToWorld() */ public class EntityFactoryManager extends Manager { public static final String TAG = EntityFactoryManager.class.getSimpleName(); private final Array<Entity> notOfThisWorld; private final FileHandle jsonFile; private String componentPackage; private ComponentMapper<? extends Component> jsonKeyMapper; private boolean debugEntityCreation; private Class<? extends Component> jsonClass; private EntityFactoryManager(FileHandle jsonFile, Class<? extends Component> jsonClass, boolean debugCreation) { super(); this.jsonFile = jsonFile; this.jsonClass = jsonClass; this.componentPackage = jsonClass.getPackage().getName(); this.debugEntityCreation = debugCreation; notOfThisWorld = new Array<Entity>(); } public static <T extends Component & JsonId> EntityFactoryManager from(FileHandle jsonFile, Class<T> jsonClass, boolean debugCreation) { return new EntityFactoryManager(jsonFile, jsonClass, debugCreation); } public static <T extends Component & JsonId> EntityFactoryManager from(FileHandle jsonFile, Class<T> jsonClass) { return from(jsonFile, jsonClass, false); } @Override @SuppressWarnings("unchecked") protected void initialize() { jsonKeyMapper = (ComponentMapper<? extends Component>)world.getMapper((Class<Component>)jsonClass); } public Entity create(Array<Component> components, String tag) { Entity entity; String id = getEntityTypeId(components); if (id != null) // creating entity w/ components from base type entity = create(id, tag); else entity = createEntity(tag); for (int i = 0, s = components.size; s > i; i++) { entity.addComponent(components.get(i)); } return entity; } public Entity create(Array<Component> components) { return create(components, null); } public Entity create(String id) { return create(id, null); } public Entity create(String id, String tag) { Entity entity = createEntity(tag); entity.addComponent(createJsonKey(id)); injectComponents(entity, id); return entity; } private Component createJsonKey(String id) { try { Component json = jsonClass.newInstance(); return ((JsonId)json).name(id); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } private Entity createEntity(String tag) { Entity entity = world.createEntity(); notOfThisWorld.add(entity); if (tag != null) world.getManager(TagManager.class).register(tag, entity); if (debugEntityCreation) Logger.log(TAG, "Created entity=%s tag=%s", getEntityIdString(entity), tag); return entity; } private String getEntityIdString(Entity e) { if (jsonKeyMapper.has(e)) return ((JsonId)jsonKeyMapper.get(e)).name(); else return String.valueOf(e.getId()); } public void delayedAdd(Entity e) { notOfThisWorld.add(e); } /** * When adding entities to the world during a process loop, managers and possibly systems * might not get notified. Hence, call this method before {@link World#process()}. */ public void addNewToWorld() { if (notOfThisWorld.size == 0) return; if (debugEntityCreation) Logger.log(TAG, "Adding entities to world: %d", notOfThisWorld.size); for (int i = 0, s = notOfThisWorld.size; s > i; i++) { world.addEntity(notOfThisWorld.get(i)); } notOfThisWorld.clear(); } private static String getEntityTypeId(Array<Component> components) { for (int i = 0; components.size > i; i++) { if (components.get(i) instanceof JsonId) return ((JsonId)components.get(i)).name(); } return null; } private Array<Component> injectComponents(Entity entity, String entityType) { FactoryInstance factory = JsonComponentFactory.from(jsonFile, componentPackage); Array<Component> parsed = factory.getComponents(entityType); for (int i = 0, s = parsed.size; s > i; i++) { entity.addComponent(parsed.get(i)); } return parsed; } }