using DCFApixels.DragonECS.Utils; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { //TODO этот класс требует переработки, изначально такая конструкция имела хорошую производительность, но сейчас он слишком раздулся 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(Type worldType) { WorldTypeMeta meta = new WorldTypeMeta(worldType); 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 worldType) { if (!_worldIds.TryGetValue(worldType, out int id)) { id = GetToken(worldType); _worldIds.Add(worldType, id); } return id; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Type GetWorldType(int worldTypeID) => _metas[worldTypeID].worldType; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetWorldID() => WorldIndex.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetComponentID(int worldID) => Component.Get(worldID); public static int GetComponentID(Type type, int worldID) => _metas[worldID].GetComponentID(type); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetPoolID(int worldID) => Pool.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 public static class PoolComponentIdArrays { private static Dictionary _componentTypeArrayPairs = new Dictionary(); public static int[] GetIdsArray(Type type) { int targetSize = _tokenCount; if (!_componentTypeArrayPairs.TryGetValue(type, out int[] result)) { result = new int[targetSize]; for (int i = 0; i < result.Length; i++) result[i] = -1; _componentTypeArrayPairs.Add(type, result); } else { if(result.Length < targetSize) { int oldSize = result.Length; Array.Resize(ref result, targetSize); ArrayUtility.Fill(result, -1, oldSize, targetSize); _componentTypeArrayPairs[type] = result; } } return result; } public static int GetComponentID(Type type, int token) { GetIdsArray(type); ref int id = ref _componentTypeArrayPairs[type][token]; if (id < 0) { var meta = _metas[token]; id = meta.componentCount++; meta.AddType(id, type); } return id; } } private static class Pool { public static int[] ids; private static Type componentType = typeof(T).GetGenericArguments()[0]; static Pool() { ids = PoolComponentIdArrays.GetIdsArray(componentType); _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) { id = PoolComponentIdArrays.GetComponentID(componentType, token); } return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { ids = PoolComponentIdArrays.GetIdsArray(componentType); } } } private static class Component { public static int[] ids; static Component() { ids = PoolComponentIdArrays.GetIdsArray(typeof(T)); _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Get(int token) { ref int id = ref ids[token]; if (id < 0) { id = PoolComponentIdArrays.GetComponentID(typeof(T), token); } return id; } private sealed class Resizer : ResizerBase { public override Type Type => typeof(T); public override int[] IDS => ids; public override void Resize(int size) { ids = PoolComponentIdArrays.GetIdsArray(typeof(T)); } } } 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 public struct XXX : IEcsComponent { } private class WorldTypeMeta { public readonly Type worldType; 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) { return PoolComponentIdArrays.GetComponentID(type, id); } public WorldTypeMeta(Type worldType) { _types = new Type[10]; _declaredComponentTypes = new Dictionary(); this.worldType = worldType; } } } }