From 4f980092560a1e7f07874e2d62b3f4dd346f83bb Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 21 Jun 2023 01:37:05 +0800 Subject: [PATCH] redesign world components --- src/DataInterfaces.cs | 117 +++++++++++++++++++++++++++++++++++++ src/EcsWorld.cs | 123 ++++++++++++--------------------------- src/Pools/EcsPoolBase.cs | 74 ----------------------- 3 files changed, 153 insertions(+), 161 deletions(-) create mode 100644 src/DataInterfaces.cs diff --git a/src/DataInterfaces.cs b/src/DataInterfaces.cs new file mode 100644 index 0000000..8bc9fb5 --- /dev/null +++ b/src/DataInterfaces.cs @@ -0,0 +1,117 @@ +using DCFApixels.DragonECS.Internal; +using System; +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS +{ + #region IEcsWorldComponent + public interface IEcsWorldComponent + { + void Init(ref T component, EcsWorld world); + } + public static class EcsWorldComponentHandler + { + public static readonly IEcsWorldComponent instance; + public static readonly bool isHasHandler; + static EcsWorldComponentHandler() + { + Type targetType = typeof(T); + isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsWorldComponent<>).MakeGenericType(targetType)); + if (isHasHandler) + { + instance = (IEcsWorldComponent)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType)); + } + else + { + instance = new DummyHandler(); + } + } + private class DummyHandler : IEcsWorldComponent + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Init(ref T component, EcsWorld world) { } + } + } + internal class WorldComponentHandler : IEcsWorldComponent + where T : IEcsWorldComponent + { + private T _fakeInstnace; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world); + } + #endregion + + #region IEcsComponentReset + public interface IEcsComponentReset + { + void Reset(ref T component); + } + public static class EcsComponentResetHandler + { + public static readonly IEcsComponentReset instance; + public static readonly bool isHasHandler; + static EcsComponentResetHandler() + { + Type targetType = typeof(T); + isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType)); + if (isHasHandler) + { + instance = (IEcsComponentReset)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType)); + } + else + { + instance = new DummyHandler(); + } + } + private sealed class DummyHandler : IEcsComponentReset + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Reset(ref T component) => component = default; + } + } + internal sealed class ComponentResetHandler : IEcsComponentReset + where T : IEcsComponentReset + { + private T _fakeInstnace; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Reset(ref T component) => _fakeInstnace.Reset(ref component); + } + #endregion + + #region IEcsComponentCopy + public interface IEcsComponentCopy + { + void Copy(ref T from, ref T to); + } + public static class EcsComponentCopyHandler + { + public static readonly IEcsComponentCopy instance; + public static readonly bool isHasHandler; + static EcsComponentCopyHandler() + { + Type targetType = typeof(T); + isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentCopy<>).MakeGenericType(targetType)); + if (isHasHandler) + { + instance = (IEcsComponentCopy)Activator.CreateInstance(typeof(ComponentCopyHandler<>).MakeGenericType(targetType)); + } + else + { + instance = new DummyHandler(); + } + } + private sealed class DummyHandler : IEcsComponentCopy + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Copy(ref T from, ref T to) => to = from; + } + } + internal sealed class ComponentCopyHandler : IEcsComponentCopy + where T : IEcsComponentCopy + { + private T _fakeInstnace; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to); + } + #endregion +} diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 5f6206f..7787bff 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -7,16 +7,49 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - public abstract class EcsWorld + public abstract partial class EcsWorld { private const short GEN_BITS = 0x7fff; private const short DEATH_GEN_BIT = short.MinValue; private const int DEL_ENT_BUFFER_SIZE_OFFSET = 2; - internal static EcsWorld[] Worlds = new EcsWorld[8]; + internal static EcsWorld[] Worlds = new EcsWorld[4]; private static IntDispenser _worldIdDispenser = new IntDispenser(0); + + static EcsWorld() + { + Worlds[0] = new EcsNullWorld(); + } + public static EcsWorld GetWorld(int worldID) => Worlds[worldID]; + private static class WorldComponentPool + { + private static T[] _items = new T[4]; + private static int[] _mapping = new int[4]; + private static int _count; + private static IEcsWorldComponent _interface = EcsWorldComponentHandler.instance; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T Get(int itemIndex) => ref _items[itemIndex]; + public static int GetItemIndex(int worldID) + { + if (_mapping.Length < Worlds.Length) + Array.Resize(ref _mapping, Worlds.Length); + + ref int itemIndex = ref _mapping[worldID]; + if (itemIndex <= 0) + { + itemIndex = ++_count; + _interface.Init(ref _items[itemIndex], Worlds[worldID]); + } + return itemIndex; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T GetForWorld(int worldID) => ref _items[GetItemIndex(worldID)]; + } + } + public abstract partial class EcsWorld + { public readonly short id; private Type _worldType; @@ -44,8 +77,6 @@ namespace DCFApixels.DragonECS private List _listeners = new List(); private List _entityListeners = new List(); - private object[] _components = new object[2]; - #region Properties public int WorldTypeID => _worldTypeID; public int Count => _entitiesCount; @@ -55,10 +86,6 @@ namespace DCFApixels.DragonECS #endregion #region Constructors/Destroy - static EcsWorld() - { - Worlds[0] = new EcsNullWorld(); - } public EcsWorld() : this(true) { } internal EcsWorld(bool isIndexable) { @@ -156,80 +183,7 @@ namespace DCFApixels.DragonECS } return (TExecutor)result; } - #endregion - - #region WorldComponents - public EcsWorld SetupComponents(IEnumerable components, params object[] componentsParams) - { - foreach (var component in components) - SetComponent(component); - foreach (var component in componentsParams) - SetComponent(component); - return this; - } - public EcsWorld SetupComponents(params object[] components) - { - foreach (var component in components) - SetComponent(component); - return this; - } - public void SetComponent(object component) - { - Type componentType = component.GetType(); - if (componentType.IsValueType || componentType.IsPrimitive) - throw new ArgumentException(); - SetComponentInternal(WorldMetaStorage.GetWorldComponentID(componentType, _worldTypeID), component); - } - public void SetComponent(T component) where T : class - { - SetComponentInternal(WorldMetaStorage.GetWorldComponentID(_worldTypeID), component); - } - private void SetComponentInternal(int index, object component) - { - if (index >= _components.Length) - Array.Resize(ref _components, _components.Length << 1); - - ref var currentComponent = ref _components[index]; - if (currentComponent == component) - return; - if (currentComponent != null && currentComponent is IEcsWorldComponent oldComponentInterface) - oldComponentInterface.OnRemovedFromWorld(this); - currentComponent = component; - if (component is IEcsWorldComponent newComponentInterface) - newComponentInterface.OnAddedToWorld(this); - } - public T GetComponent() where T : class - { - if (!TryGetComponent(out T result)) - throw new NullReferenceException(); - return result; - } - public bool TryGetComponent(out T component) where T : class - { - int index = WorldMetaStorage.GetWorldComponentID(_worldTypeID); - if (index >= _components.Length) - { - component = null; - return false; - } - component = (T)_components[index]; - return component != null; - } - public bool HasComponent() - { - int index = WorldMetaStorage.GetWorldComponentID(_worldTypeID); - if (index >= _components.Length) - return false; - return _components[index] != null; - } - public void RemoveComponent() - { - int index = WorldMetaStorage.GetWorldComponentID(_worldTypeID); - ref var currentComponent = ref _components[index]; - if (currentComponent is IEcsWorldComponent componentInterface) - componentInterface.OnRemovedFromWorld(this); - currentComponent = null; - } + public ref T GetComponent() where T : struct => ref WorldComponentPool.GetForWorld(id); #endregion #region Where Query @@ -455,11 +409,6 @@ namespace DCFApixels.DragonECS internal sealed class EcsNullWorld : EcsWorld { } #region Callbacks Interface - public interface IEcsWorldComponent - { - void OnAddedToWorld(EcsWorld world); - void OnRemovedFromWorld(EcsWorld world); - } public interface IEcsWorldEventListener { void OnWorldResize(int newSize); diff --git a/src/Pools/EcsPoolBase.cs b/src/Pools/EcsPoolBase.cs index 909629d..ebfd812 100644 --- a/src/Pools/EcsPoolBase.cs +++ b/src/Pools/EcsPoolBase.cs @@ -121,80 +121,6 @@ namespace DCFApixels.DragonECS } #endregion - #region Reset/Copy interfaces - public interface IEcsComponentReset - { - void Reset(ref T component); - } - public static class EcsComponentResetHandler - { - public static readonly IEcsComponentReset instance; - public static readonly bool isHasHandler; - static EcsComponentResetHandler() - { - Type targetType = typeof(T); - if (targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType))) - { - instance = (IEcsComponentReset)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType)); - isHasHandler = true; - } - else - { - instance = new ComponentResetDummyHandler(); - isHasHandler = false; - } - } - } - internal sealed class ComponentResetDummyHandler : IEcsComponentReset - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset(ref T component) => component = default; - } - internal sealed class ComponentResetHandler : IEcsComponentReset - where T : IEcsComponentReset - { - private T _fakeInstnace = default; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset(ref T component) => _fakeInstnace.Reset(ref component); - } - - public interface IEcsComponentCopy - { - void Copy(ref T from, ref T to); - } - public static class EcsComponentCopyHandler - { - public static readonly IEcsComponentCopy instance; - public static readonly bool isHasHandler; - static EcsComponentCopyHandler() - { - Type targetType = typeof(T); - if (targetType.GetInterfaces().Contains(typeof(IEcsComponentCopy<>).MakeGenericType(targetType))) - { - instance = (IEcsComponentCopy)Activator.CreateInstance(typeof(ComponentCopyHandler<>).MakeGenericType(targetType)); - isHasHandler = true; - } - else - { - instance = new ComponentCopyDummyHandler(); - isHasHandler = false; - } - } - } - internal sealed class ComponentCopyDummyHandler : IEcsComponentCopy - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Copy(ref T from, ref T to) => to = from; - } - internal sealed class ComponentCopyHandler : IEcsComponentCopy - where T : IEcsComponentCopy - { - private T _fakeInstnace = default; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to); - } - #endregion - #region Callbacks Interface public interface IEcsPoolEventListener {