using DCFApixels.DragonECS.Utils; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { internal static class WorldMetaStorage { private static int _tokenCount = 0; private static List _resizers = new List(); private static WorldTypeMeta[] _metas = new WorldTypeMeta[0]; private static Dictionary _worldIds = new Dictionary(); private static class WorldIndex { public static int id = GetWorldID(typeof(TWorldArchetype)); } private static int GetToken() { WorldTypeMeta meta = new WorldTypeMeta(); meta.id = _tokenCount; Array.Resize(ref _metas, ++_tokenCount); _metas[_tokenCount - 1] = meta; foreach (var item in _resizers) item.Resize(_tokenCount); return _tokenCount - 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetWorldID(Type archetype) { if (!_worldIds.TryGetValue(archetype, out int id)) { id = GetToken(); _worldIds.Add(archetype, id); } return id; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetWorldId() => WorldIndex.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetComponentId(int worldID) => Component.Get(worldID); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetSubjectId(int worldID) => Subject.Get(worldID); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetExecutorId(int worldID) => Executor.Get(worldID); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetWorldComponentId(int worldID) => WorldComponent.Get(worldID); public static bool IsComponentTypeDeclared(int worldID, Type type) => _metas[worldID].IsDeclaredType(type); public static Type GetComponentType(int worldID, int componentID) => _metas[worldID].GetComponentType(componentID); private abstract class ResizerBase { public abstract Type Type { get; } public abstract int[] IDS { get; } public abstract void Resize(int size); } #region Containers private static class Pool { public static int[] ids; static Pool() { ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) { var meta = _metas[token]; id = meta.GetComponentID(typeof(T).GetGenericArguments()[0]); meta.AddType(id, typeof(T)); } return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { int oldSize = ids.Length; Array.Resize(ref ids, size); ArrayUtility.Fill(ids, -1, oldSize, size); } } } private static class Component { public static int[] ids; static Component() { ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) { var meta = _metas[token]; id = meta.componentCount++; meta.AddType(id, typeof(T)); } return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { int oldSize = ids.Length; Array.Resize(ref ids, size); ArrayUtility.Fill(ids, -1, oldSize, size); } } } private static class Subject { public static int[] ids; static Subject() { ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) id = _metas[token].subjectsCount++; return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { int oldSize = ids.Length; Array.Resize(ref ids, size); ArrayUtility.Fill(ids, -1, oldSize, size); } } } private static class Executor { public static int[] ids; static Executor() { ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) id = _metas[token].executorsCount++; return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { int oldSize = ids.Length; Array.Resize(ref ids, size); ArrayUtility.Fill(ids, -1, oldSize, size); } } } private static class WorldComponent { public static int[] ids; static WorldComponent() { ids = new int[_tokenCount]; for (int i = 0; i < ids.Length; i++) ids[i] = -1; _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) id = _metas[token].worldComponentCount++; return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { int oldSize = ids.Length; Array.Resize(ref ids, size); ArrayUtility.Fill(ids, -1, oldSize, size); } } } #endregion private class WorldTypeMeta { public int id; public int componentCount; public int subjectsCount; public int executorsCount; public int worldComponentCount; private Type[] _types; private Dictionary _declaredComponentTypes; public void AddType(int id, Type type) { if (_types.Length <= id) Array.Resize(ref _types, id + 10); _types[id] = type; _declaredComponentTypes.Add(type, id); } public Type GetComponentType(int componentID) => _types[componentID]; public bool IsDeclaredType(Type type) => _declaredComponentTypes.ContainsKey(type); public int GetComponentID(Type type) { if (!IsDeclaredType(type)) { RuntimeHelpers.RunClassConstructor(type.TypeHandle); typeof(Component<>).MakeGenericType(type); } return _declaredComponentTypes[type]; } public WorldTypeMeta() { _types = new Type[10]; _declaredComponentTypes = new Dictionary(); } } } }