package net.fourbytes.shadow.systems; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.reflect.ArrayReflection; import com.badlogic.gdx.utils.reflect.ClassReflection; import net.fourbytes.shadow.Level; import net.fourbytes.shadow.mod.ModManager; import net.fourbytes.shadow.utils.Cache; public class DefaultSystemManager implements ISystemManager { protected final Cache<Array<ISystem>> cache = new Cache(Array.class, 64, new Object[] {false, 16, ISystem.class}, new Class[] {boolean.class, int.class, Class.class}); protected final ObjectMap<Class<?>, Object[]> gotAll = new ObjectMap<Class<?>, Object[]>(); public Level level; public ObjectMap<String, ISystem> systemmap = new ObjectMap<String, ISystem>(); public ObjectMap<Class<? extends ISystem>, ISystem> isystemmap = new ObjectMap<Class<? extends ISystem>, ISystem>(); public Array<ISystem> systems = new Array<ISystem>(ISystem.class); public DefaultSystemManager(Level level) { this.level = level; } @Override public void init() { init("ParticleManager"); init("LightSystem"); init("WeatherSystem"); init("TimeDaySystem"); init("MusicSystem"); ModManager.initLevelSystems(level); } @Override public void init(String name) { if (systemmap.containsKey(name)) { return; } ISystem system = ModManager.initLevelSystem(level, name); if (system == null) { try { Class<? extends ISystem> clazz = ClassReflection.forName("net.fourbytes.shadow.systems.Default"+name); system = clazz.getConstructor(Level.class).newInstance(level); } catch (Exception e) { //System not found or other error - ignore. } } if (system == null || !name.equals(system.getName())) { return; } set(name, system); } @Override public void set(String name, ISystem system) { if (system == null) { return; } ISystem systemPrevious = systemmap.get(name); if (systemPrevious != null) { systems.removeValue(systemPrevious, true); } systems.add(system); systemmap.put(name, system); Class clazzISystem = ISystem.class; Class clazz = system.getClass(); Class<?>[] clazzInterfaces = clazz.getInterfaces(); for (Class<?> i : clazzInterfaces) { if (clazzISystem.isAssignableFrom(i)) { isystemmap.put((Class<? extends ISystem>) i, system); } } gotAll.clear(); } @Override public ISystem get(String name) { return systemmap.get(name); } @Override public <T> T get(Class<T> isystem) { return (T) isystemmap.get((Class<? extends ISystem>) isystem); } @Override public <T> T[] getAll(Class<T> clazz) { Object[] got = gotAll.get(clazz); if (got != null) { return (T[]) got; } Array<ISystem> matching = cache.getNext(); matching.clear(); for (int i = 0; i < systems.size; i++) { ISystem system = systems.items[i]; if (clazz.isAssignableFrom(system.getClass())) { matching.add(system); } } T[] array = (T[]) ArrayReflection.newInstance(clazz, matching.size); System.arraycopy(matching.items, 0, array, 0, array.length); gotAll.put(clazz, array); return array; } @Override public ISystem[] getAll() { return systems.toArray(); } @Override public void tick(float delta) { ITickable[] tickables = getAll(ITickable.class); for (int i = 0; i < tickables.length; i++) { ITickable tickable = tickables[i]; tickable.tick(delta); } } @Override public String getName() { return null; } }