#if false using Ghost.Core; using Misaki.HighPerformance.Collections; using System.Runtime.CompilerServices; namespace Ghost.Entities; public interface IManagedComponent; public interface IManagedWrapper; public readonly struct Managed : IComponent, IManagedWrapper where T : IManagedComponent { public readonly int id; public readonly int generation; internal Managed(int id, int generation) { this.id = id; this.generation = generation; } } public static class ManagedComponemtnID where T : IManagedComponent { public static readonly Identifier value = ManagedComponentRegistry.GetOrRegisterComponent(); } internal struct ManagedComponentInfo { public int id; public bool isScriptComponent; } internal static class ManagedComponentRegistry { private static readonly List s_registeredComponents = new(); private static readonly Dictionary s_typeHandleToID = new(); private static readonly Dictionary s_nameToRuntimeID = new(); #if DEBUG || GHOST_EDITOR internal static readonly Dictionary s_runtimeIDToType = new(); #endif public static Identifier GetOrRegisterComponent() where T : IManagedComponent { var typeHandle = typeof(T).TypeHandle.Value; lock (s_registeredComponents) { if (s_typeHandleToID.TryGetValue(typeHandle, out var existingID)) { return existingID; } var newID = new Identifier(s_registeredComponents.Count); var stableName = typeof(T).FullName ?? typeof(T).Name; var info = new ManagedComponentInfo { id = newID, isScriptComponent = typeof(ScriptComponent).IsAssignableFrom(typeof(T)), }; s_registeredComponents.Add(info); s_typeHandleToID[typeHandle] = newID; s_nameToRuntimeID[stableName] = newID; #if DEBUG || GHOST_EDITOR s_runtimeIDToType[newID.value] = typeof(T); #endif return newID; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Identifier GetComponentID(Type type) { var typeHandle = type.TypeHandle.Value; lock (s_registeredComponents) { if (s_typeHandleToID.TryGetValue(typeHandle, out var existingID)) { return existingID; } } return Identifier.Invalid; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ManagedComponentInfo GetComponentInfo(Identifier typeId) { lock (s_registeredComponents) { return s_registeredComponents[typeId]; } } } internal interface IManagedComponentStorage { public Identifier TypeID { get; } } internal class ManagedComponentStorage : IManagedComponentStorage where T : IManagedComponent { private readonly SlotMap _storage = new(16); public Identifier TypeID => ManagedComponemtnID.value; public Managed Add(T component) { var id = _storage.Add(component, out var generation); return new Managed(id, generation); } public void Remove(Managed managed) { _storage.Remove(managed.id, managed.generation); } public ref T GetComponentReference(Managed managed) { return ref _storage.GetElementReferenceAt(managed.id, managed.generation, out _); } } public abstract class ScriptComponent : IManagedComponent { internal World _world = null!; internal Entity _entity; public World World => _world; public Entity Entity => _entity; protected ref T GetComponent() where T : unmanaged, IComponent { return ref _world.EntityManager.GetComponent(_entity); } public virtual void OnCreate() { } public virtual void OnDestroy() { } public virtual void OnEnable() { } public virtual void OnDisable() { } public virtual void Start() { } public virtual void Update() { } public virtual void FixedUpdate() { } public virtual void LateUpdate() { } } public partial class EntityManager { private IManagedComponentStorage[] _storages; internal IManagedComponentStorage[] Storages => _storages; private ManagedComponentStorage GetOrCreateManagedComponentStorage() where T : IManagedComponent { var id = ManagedComponemtnID.value; if (_storages == null || _storages.Length <= id.value) { Array.Resize(ref _storages, id.value + 1); } ref var storage = ref _storages[id.value]; storage ??= new ManagedComponentStorage(); return (ManagedComponentStorage)storage; } public Managed AddManagedComponent(Entity entity) where T : IManagedComponent, new() { var instance = new T(); if (instance is ScriptComponent scriptComponent) { scriptComponent._world = _world; scriptComponent._entity = entity; scriptComponent.OnCreate(); } var managed = GetOrCreateManagedComponentStorage().Add(instance); AddComponent(entity, managed); return managed; } public bool RemoveManagedComponent(Entity entity) where T : IManagedComponent { ref var component = ref GetComponent>(entity); if (!Unsafe.IsNullRef(ref component)) { var storage = GetOrCreateManagedComponentStorage(); var componentRef = storage.GetComponentReference(component); if (componentRef is ScriptComponent scriptComponent) { scriptComponent.OnDestroy(); } RemoveComponent>(entity); storage.Remove(component); return true; } return false; } public ref T GetManagedComponent(Entity entity) where T : IManagedComponent { ref var component = ref GetComponent>(entity); if (Unsafe.IsNullRef(ref component)) { return ref Unsafe.NullRef(); } return ref GetOrCreateManagedComponentStorage().GetComponentReference(component); } public ref T GetManagedComponent(Managed managedComponent) where T : IManagedComponent { return ref GetOrCreateManagedComponentStorage().GetComponentReference(managedComponent); } } #endif