This commit is contained in:
Mikhail 2023-03-26 11:19:03 +08:00
parent 9a8e4a6995
commit e2ebe33b57
20 changed files with 723 additions and 387 deletions

8
src/Attributes.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 269d1f5d46517e14a8563d7f239fa559
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
using System;
using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS
{
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class DebugColorAttribute : Attribute
{
private ColorRecord color;
public byte r => color.r;
public byte g => color.g;
public byte b => color.b;
public DebugColorAttribute(byte r, byte g, byte b)
{
color = new ColorRecord(r, g, b);
}
public DebugColorAttribute(DebugColor color)
{
this.color = new ColorRecord((int)color);
}
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
private readonly struct ColorRecord
{
[FieldOffset(0)]
public readonly int full;
[FieldOffset(3)]
public readonly byte r;
[FieldOffset(2)]
public readonly byte g;
[FieldOffset(1)]
public readonly byte b;
public ColorRecord(byte r, byte g, byte b) : this()
{
this.r = r;
this.g = g;
this.b = b;
}
public ColorRecord(int full) : this()
{
this.full = full;
}
}
}
public enum DebugColor
{
/// <summary> Red. RGB is (255, 0, 0)</summary>
Red = 255 << 8 * 3 + 000 << 8 * 2 + 000 << 8,
/// <summary> Green. RGB is (0, 255, 0)</summary>
Green = 000 << 8 * 3 + 255 << 8 * 2 + 000 << 8,
/// <summary> Blue. RGB is (0, 0, 255)</summary>
Blue = 000 << 8 * 3 + 000 << 8 * 2 + 255 << 8,
/// <summary> Yellow. RGB is (255, 255, 0)</summary>
Yellow = 255 << 8 * 3 + 255 << 8 * 2 + 000 << 8,
/// <summary> Cyan. RGB is (0, 255, 255)</summary>
Cyan = 000 << 8 * 3 + 255 << 8 * 2 + 255 << 8,
/// <summary> Magenta. RGB is (255, 0, 255)</summary>
Magenta = 255 << 8 * 3 + 000 << 8 * 2 + 000 << 8,
/// <summary> Yellow. RGB is (255, 127, 0)</summary>
Orange = (255 << 24) + (127 << 16) + (000 << 8),
/// <summary> Grey/Gray. RGB is (127, 127, 127)</summary>
Gray = 127 << 8 * 3 + 127 << 8 * 2 + 127 << 8,
/// <summary> Grey/Gray. RGB is (127, 127, 127)</summary>
Grey = Gray,
/// <summary> White. RGB is (255, 255, 255)</summary>
White = -1,
/// <summary> Black. RGB is (0, 0, 0)</summary>
Black = 0,
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2ae31658c78bbf04cb755ac72be367dd
guid: 4b96ad0ff9cf7124d8539afccec8f1ae
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -2,53 +2,49 @@
{
public interface IEcsPreInitSystem : IEcsSystem
{
public void PreInit(EcsSession session);
public void PreInit(EcsSystems systems);
}
public interface IEcsInitSystem : IEcsSystem
{
public void Init(EcsSession session);
public void Init(EcsSystems systems);
}
public interface IEcsRunSystem : IEcsSystem
{
public void Run(EcsSession session);
public void Run(EcsSystems systems);
}
public interface IEcsDestroySystem : IEcsSystem
{
public void Destroy(EcsSession session);
public void Destroy(EcsSystems systems);
}
public interface IEcsBaseSystem :
IEcsInitSystem,
IEcsRunSystem,
IEcsDestroySystem
{ }
public interface IEcsBaseSystem : IEcsInitSystem, IEcsRunSystem, IEcsDestroySystem { }
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem
{
void IEcsPreInitSystem.PreInit(EcsSession session)
void IEcsPreInitSystem.PreInit(EcsSystems systems)
{
foreach (var item in targets) item.PreInit(session);
foreach (var item in targets) item.PreInit(systems);
}
}
public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem
{
void IEcsInitSystem.Init(EcsSession session)
void IEcsInitSystem.Init(EcsSystems systems)
{
foreach (var item in targets) item.Init(session);
foreach (var item in targets) item.Init(systems);
}
}
public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem
{
void IEcsRunSystem.Run(EcsSession session)
void IEcsRunSystem.Run(EcsSystems systems)
{
foreach (var item in targets) item.Run(session);
foreach (var item in targets) item.Run(systems);
}
}
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem
{
void IEcsDestroySystem.Destroy(EcsSession session)
void IEcsDestroySystem.Destroy(EcsSystems systems)
{
foreach (var item in targets) item.Destroy(session);
foreach (var item in targets) item.Destroy(systems);
}
}
}

View File

@ -4,6 +4,7 @@
{
public void Inject(T obj);
}
[DebugColor(DebugColor.Gray)]
public sealed class InjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
{
void IEcsInject<T>.Inject(T obj)
@ -15,6 +16,7 @@
}
}
[DebugColor(DebugColor.Gray)]
public class InjectSystem<T> : IEcsPreInitSystem
{
private T _injectedData;
@ -24,37 +26,38 @@
_injectedData = injectedData;
}
public void PreInit(EcsSession session)
public void PreInit(EcsSystems systems)
{
var injector = session.GetRunner<IEcsInject<T>>();
var injector = systems.GetRunner<IEcsInject<T>>();
injector.Inject(_injectedData);
}
}
public static class InjectSystemExstensions
{
public static EcsSession Inject<T>(this EcsSession self, T data)
public static EcsSystems.Builder Inject<T>(this EcsSystems.Builder self, T data)
{
self.Add(new InjectSystem<T>(data));
return self;
}
public static EcsSession Inject<A, B>(this EcsSession self, A dataA, B dataB)
public static EcsSystems.Builder Inject<A, B>(this EcsSystems.Builder self, A a, B b)
{
self.Inject(dataA).Inject(dataB);
self.Inject(a).Inject(b);
return self;
}
public static EcsSession Inject<A, B, C, D>(this EcsSession self, A dataA, B dataB, C dataC, D dataD)
public static EcsSystems.Builder Inject<A, B, C, D>(this EcsSystems.Builder self, A a, B b, C c, D d)
{
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD);
self.Inject(a).Inject(b).Inject(c).Inject(d);
return self;
}
public static EcsSession Inject<A, B, C, D, E>(this EcsSession self,
A dataA, B dataB, C dataC, D dataD, E dataE)
public static EcsSystems.Builder Inject<A, B, C, D, E>(this EcsSystems.Builder self, A a, B b, C c, D d, E e)
{
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD).Inject(dataE);
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e);
return self;
}
public static EcsSystems.Builder Inject<A, B, C, D, E, F>(this EcsSystems.Builder self, A a, B b, C c, D d, E e, F f)
{
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f);
return self;
}
}

8
src/Consts.cs Normal file
View File

@ -0,0 +1,8 @@
namespace DCFApixels.DragonECS
{
public class EcsConsts
{
public const string EXCEPTION_MESSAGE_PREFIX = "[DragonECS] ";
public const string DEBUG_PREFIX = "[DEBUG] ";
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f04087406e09f6042a341cf8fc41fabf
guid: 3c30dd6d8ecfdbd4aaceccd22bfb85c4
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -13,31 +13,193 @@ namespace DCFApixels.DragonECS
#region Incs
public interface IInc : IMaskCondition { }
public struct Inc : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
}
public struct Inc<T0> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>()
where TWorldArchetype : IWorldArchetype
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
};
}
}
public struct Inc<T0, T1> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>()
where TWorldArchetype : IWorldArchetype
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T10>.uniqueID,
};
}
}
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : IInc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T10>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T11>.uniqueID,
};
}
}
@ -45,15 +207,13 @@ namespace DCFApixels.DragonECS
#region Excs
public interface IExc : IMaskCondition { }
public struct Exc : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
}
public struct Exc<T0> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>()
where TWorldArchetype : IWorldArchetype
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
@ -63,13 +223,66 @@ namespace DCFApixels.DragonECS
}
public struct Exc<T0, T1> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>()
where TWorldArchetype : IWorldArchetype
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
};
}
}
public struct Exc<T0, T1, T2> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
};
}
}
public struct Exc<T0, T1, T2, T3> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
};
}
}
public struct Exc<T0, T1, T2, T3, T4> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
};
}
}
public struct Exc<T0, T1, T2, T3, T4, T5> : IExc
{
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
{
return new int[]
{
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
};
}
}
@ -238,19 +451,4 @@ namespace DCFApixels.DragonECS
#endregion
}
#endregion
#region Utils
internal static class ArrayExt
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static T[] Sort<T>(this T[] self)
{
Array.Sort(self);
return self;
}
}
#endregion
}

View File

@ -31,7 +31,7 @@ namespace DCFApixels.DragonECS
#endregion
#region Constrcutors
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 32)
{
_source = world;
_entities = new SparseSet(entitiesCapacity, entitiesCapacity);
@ -67,6 +67,11 @@ namespace DCFApixels.DragonECS
}
#endregion
#region Contains
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(int entityID) => _entities.Contains(entityID);
#endregion
#region AddGroup/RemoveGroup
public void AddGroup(IEcsReadonlyGroup group)
{
@ -124,44 +129,28 @@ namespace DCFApixels.DragonECS
private readonly EcsGroup _source;
private readonly SparseSet _entities;
private int _index;
private Entity _currentEntity;
public Enumerator(EcsGroup group)
{
_source = group;
_entities = group._entities;
_index = -1;
_currentEntity = new Entity(group.World, -1);
}
public Entity Current
public ent Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
_currentEntity.id = _entities[_index];
return _currentEntity;
}
get { return _source.World.GetEntity(_entities[_index]); }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
return ++_index < _entities.Count;
}
public bool MoveNext() => ++_index < _entities.Count;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
_source.Unlock();
}
public void Dispose() => _source.Unlock();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_index = -1;
_currentEntity.id = -1;
}
public void Reset() => _index = -1;
}
private struct DelayedOp

View File

@ -1,7 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;

View File

@ -1,5 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
@ -25,7 +28,12 @@ namespace DCFApixels.DragonECS
}
public interface IEcsSystem { }
public interface IEcsRunner { }
public interface IEcsRunner
{
public IList Targets { get; }
public object Filter { get; }
public bool IsHasFilter { get; }
}
public static class IEcsProcessorExtensions
@ -36,10 +44,9 @@ namespace DCFApixels.DragonECS
}
}
internal static class EcsRunnerActivator
{
private static Dictionary<Guid, Type> _runnerTypes; //interface guid/ Runner type pairs;
private static Dictionary<Guid, Type> _runnerHandlerTypes; //interface guid/Runner handler type pairs;
static EcsRunnerActivator()
{
@ -47,28 +54,28 @@ namespace DCFApixels.DragonECS
Type runnerBaseType = typeof(EcsRunner<>);
List<Type> newRunnerTypes = new List<Type>();
newRunnerTypes = Assembly.GetAssembly(runnerBaseType)
List<Type> runnerHandlerTypes = new List<Type>();
runnerHandlerTypes = Assembly.GetAssembly(runnerBaseType)
.GetTypes()
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition())
.ToList();
#if DEBUG
for (int i = 0; i < newRunnerTypes.Count; i++)
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
for (int i = 0; i < runnerHandlerTypes.Count; i++)
{
var e = CheckRunnerValide(newRunnerTypes[i]);
var e = CheckRunnerValide(runnerHandlerTypes[i]);
if (e != null)
{
newRunnerTypes.RemoveAt(i--);
runnerHandlerTypes.RemoveAt(i--);
exceptions.Add(e);
}
}
#endif
_runnerTypes = new Dictionary<Guid, Type>();
foreach (var item in newRunnerTypes)
_runnerHandlerTypes = new Dictionary<Guid, Type>();
foreach (var item in runnerHandlerTypes)
{
Type intrf = item.GetInterfaces().Where(o => o != typeof(IEcsRunner) && o != typeof(IEcsSystem)).First(); //TODO оптимизировать это место
_runnerTypes.Add(intrf.GUID, item);
Type interfaceType = item.GetInterfaces().Where(o => o != typeof(IEcsRunner) && o != typeof(IEcsSystem)).First(); //TODO оптимизировать это место
_runnerHandlerTypes.Add(interfaceType.GUID, item);
}
if (exceptions.Count > 0)
@ -102,7 +109,7 @@ namespace DCFApixels.DragonECS
}
Guid interfaceGuid = nonGenericInterfaceType.GUID;
if (!_runnerTypes.TryGetValue(interfaceGuid, out Type runnerType))
if (!_runnerHandlerTypes.TryGetValue(interfaceGuid, out Type runnerType))
{
throw new Exception();
}
@ -111,16 +118,17 @@ namespace DCFApixels.DragonECS
Type[] genericTypes = interfaceType.GetGenericArguments();
runnerType = runnerType.MakeGenericType(genericTypes);
}
EcsRunner<TInterface>.Init(runnerType);
EcsRunner<TInterface>.Register(runnerType);
}
}
public abstract class EcsRunner<TInterface> : IEcsSystem, IEcsRunner
where TInterface : IEcsSystem
{
internal static void Init(Type subclass)
#region Register
private static Type _subclass;
internal static void Register(Type subclass)
{
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
if (_subclass != null)
{
@ -141,8 +149,14 @@ namespace DCFApixels.DragonECS
#endif
_subclass = subclass;
}
#endregion
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets, object filter)
#region FilterSystems
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets)
{
return targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray();
}
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets, object filter)
{
Type interfaceType = typeof(TInterface);
@ -166,32 +180,52 @@ namespace DCFApixels.DragonECS
return atr == null || atr.interfaceType == interfaceType && atr.filter == null;
});
}
return newTargets.Select(o => (TInterface)o).ToArray();
}
#endregion
return Instantiate(newTargets.Select(o => (TInterface)o).ToArray());
}
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets)
{
return Instantiate(targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray());
}
internal static TInterface Instantiate(TInterface[] targets)
#region Instantiate
private static TInterface Instantiate(TInterface[] targets, bool isHasFilter, object filter)
{
if (_subclass == null)
EcsRunnerActivator.InitFor<TInterface>();
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
return (TInterface)(IEcsSystem)instance.Set(targets);
return (TInterface)(IEcsSystem)instance.Set(targets, isHasFilter, filter);
}
private static Type _subclass;
protected static void SetSublcass(Type type) => _subclass = type;
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets)
{
return Instantiate(FilterSystems(targets), false, null);
}
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets, object filter)
{
return Instantiate(FilterSystems(targets, filter), true, filter);
}
#endregion
protected TInterface[] targets;
private ReadOnlyCollection<TInterface> _targetsSealed;
private object _filter;
private bool _isHasFilter;
private EcsRunner<TInterface> Set(TInterface[] targets)
public IList Targets => _targetsSealed;
public object Filter => _filter;
public bool IsHasFilter => _isHasFilter;
private EcsRunner<TInterface> Set(TInterface[] targets, bool isHasFilter, object filter)
{
this.targets = targets;
_targetsSealed = new ReadOnlyCollection<TInterface>(targets);
_filter = filter;
_isHasFilter = isHasFilter;
return this;
}
internal void Rebuild(IEnumerable<IEcsSystem> targets)
{
if(_isHasFilter)
Set(FilterSystems(targets), _isHasFilter, _filter);
else
Set(FilterSystems(targets, _filter), _isHasFilter, _filter);
}
}
}

View File

@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public class EcsWorldMap
{
private Dictionary<(Type, string), IEcsWorld> _worlds = new Dictionary<(Type, string), IEcsWorld>(8);
private bool _built = false;
public void Add<TArchetype>(EcsWorld<TArchetype> world, string name = "")
where TArchetype : IWorldArchetype
{
if(_built) { throw new Exception($"Cant change built {nameof(EcsWorldMap)}"); }
_worlds.Add((typeof(TArchetype), name), world);
}
public EcsWorld<TArchetype> Get<TArchetype>(string name ="")
where TArchetype : IWorldArchetype
{
return (EcsWorld<TArchetype>)_worlds[(typeof(TArchetype), name)];
}
public IEcsWorld Get(Type type, string name = "")
{
return _worlds[(type, name)];
}
public void Build()
{
_built = true;
}
}
public class EcsSession
{
private int _id;
private readonly List<IEcsSystem> _allSystems;
private ReadOnlyCollection<IEcsSystem> _allSystemsSealed;
private bool _isInit = false;
private bool _isDestoryed = false;
private readonly Dictionary<Type, IEcsRunner> _runners;
private IEcsRunSystem _runRunnerCache;
private readonly EcsWorldMap _worldMap;
#region Properties
public ReadOnlyCollection<IEcsSystem> AllProcessors => _allSystemsSealed;
#endregion
public EcsSession()
{
_allSystems = new List<IEcsSystem>(128);
_runners = new Dictionary<Type, IEcsRunner>();
_worldMap = new EcsWorldMap();
}
#region Runners
public T GetRunner<T>() where T : IEcsSystem
{
Type type = typeof(T);
if (_runners.TryGetValue(type, out IEcsRunner result))
{
return (T)result;
}
result = (IEcsRunner)EcsRunner<T>.Instantiate(_allSystems);
_runners.Add(type, result);
return (T)result;
}
#endregion
#region Configuration
public EcsSession Add(IEcsSystem system)
{
CheckInitForMethod(nameof(AddWorld));
_allSystems.Add(system);
return this;
}
public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "")
where TArchetype : IWorldArchetype
{
CheckInitForMethod(nameof(AddWorld));
_worldMap.Add(world, name);
return this;
}
#endregion
#region LifeCycle
public EcsSession Init()
{
CheckInitForMethod(nameof(Init));
_worldMap.Build();
_allSystemsSealed = _allSystems.AsReadOnly();
_isInit = true;
GetRunner<IEcsInject<EcsWorldMap>>().Inject(_worldMap);
GetRunner<IEcsPreInitSystem>().PreInit(this);
GetRunner<IEcsInitSystem>().Init(this);
_runRunnerCache = GetRunner<IEcsRunSystem>();
return this;
}
public void Run()
{
CheckDestroyForMethod(nameof(Run));
_runRunnerCache.Run(this);
}
public void Destroy()
{
CheckDestroyForMethod(nameof(Destroy));
_isDestoryed = true;
GetRunner<IEcsDestroySystem>().Destroy(this);
}
#endregion
#region StateChecks
private void CheckInitForMethod(string methodName)
{
if (_isInit)
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после инициализации {nameof(EcsSession)}");
}
private void CheckDestroyForMethod(string methodName)
{
if (_isDestoryed)
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после уничтожения {nameof(EcsSession)}");
}
#endregion
#region EntityConvert
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Entity ToEntity(in ent target)
{
throw new NotImplementedException();
// return new Entity(null, target.id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ent ToEnt(in Entity target)
{
throw new NotImplementedException();
// return new ent(target.id, target.world._gens[target.id], -1000);
}
#endregion
#region Utils
#endregion
}
}

196
src/EcsSystems.cs Normal file
View File

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public sealed class EcsSystems
{
private IEcsSystem[] _allSystems;
private Dictionary<Type, IEcsRunner> _runners;
private IEcsRunSystem _runRunnerCache;
private ReadOnlyCollection<IEcsSystem> _allSystemsSealed;
private ReadOnlyDictionary<Type, IEcsRunner> _allRunnersSealed;
private bool _isDestoryed;
#region Properties
public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed;
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
public bool IsDestoryed => _isDestoryed;
#endregion
#region Constructors
private EcsSystems(IEcsSystem[] systems)
{
_allSystems = systems;
_runners = new Dictionary<Type, IEcsRunner>();
_allSystemsSealed = new ReadOnlyCollection<IEcsSystem>(_allSystems);
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
_isDestoryed = false;
GetRunner<IEcsPreInitSystem>().PreInit(this);
GetRunner<IEcsInitSystem>().Init(this);
_runRunnerCache = GetRunner<IEcsRunSystem>();
}
#endregion
#region Runners
public T GetRunner<T>() where T : IEcsSystem
{
Type type = typeof(T);
if (_runners.TryGetValue(type, out IEcsRunner result))
return (T)result;
result = (IEcsRunner)EcsRunner<T>.Instantiate(_allSystems);
_runners.Add(type, result);
return (T)result;
}
#endregion
#region LifeCycle
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Run()
{
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
CheckAfterDestroyForMethod(nameof(Run));
#endif
_runRunnerCache.Run(this);
}
public void Destroy()
{
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
CheckAfterDestroyForMethod(nameof(Destroy));
#endif
_isDestoryed = true;
GetRunner<IEcsDestroySystem>().Destroy(this);
}
#endregion
#region StateChecks
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
private void CheckAfterDestroyForMethod(string methodName)
{
if (_isDestoryed)
throw new MethodAccessException($"It is forbidden to call method {methodName}, after destroying {nameof(EcsSystems)}");
}
#endif
#endregion
#region Builder
public static Builder New()
{
return new Builder();
}
public class Builder
{
private const int KEYS_CAPACITY = 4;
private readonly HashSet<object> _declaredBlockKeys;
private readonly List<object> _blockExecutionOrder;
private readonly Dictionary<object, List<IEcsSystem>> _systems;
private readonly object _basicBlocKey;
private bool _isBasicBlockDeclared;
private bool _isOnlyBasicBlock;
public Builder()
{
_basicBlocKey = new object();
_declaredBlockKeys = new HashSet<object>(KEYS_CAPACITY);
_blockExecutionOrder = new List<object>(KEYS_CAPACITY);
_systems = new Dictionary<object, List<IEcsSystem>>(KEYS_CAPACITY);
_isBasicBlockDeclared = false;
_isOnlyBasicBlock = true;
}
public Builder Add(IEcsSystem system, object blockKey = null)
{
if (blockKey == null) blockKey = _basicBlocKey;
List<IEcsSystem> list;
if (!_systems.TryGetValue(blockKey, out list))
{
list = new List<IEcsSystem>();
_systems.Add(blockKey, list);
}
list.Add(system);
return this;
}
public Builder Add(IEcsModule module)
{
module.ImportSystems(this);
return this;
}
public Builder BasicSystemsBlock()
{
_isBasicBlockDeclared = true;
_blockExecutionOrder.Add(_basicBlocKey);
return this;
}
public Builder SystemsBlock(object blockKey)
{
if (blockKey == null)
return BasicSystemsBlock();
_isOnlyBasicBlock = false;
_blockExecutionOrder.Add(blockKey);
return this;
}
public EcsSystems Build()
{
if (_isOnlyBasicBlock)
{
return new EcsSystems(_systems[_basicBlocKey].ToArray());
}
if(_isBasicBlockDeclared == false)
_blockExecutionOrder.Insert(0, _basicBlocKey);
List<IEcsSystem> result = new List<IEcsSystem>(32);
List<IEcsSystem> basicBlockList = _systems[_basicBlocKey];
foreach (var item in _systems)
{
if (!_blockExecutionOrder.Contains(item.Key))
{
basicBlockList.AddRange(item.Value);
}
}
foreach (var item in _blockExecutionOrder)
{
result.AddRange(_systems[item]);
}
return new EcsSystems(result.ToArray());
}
}
#endregion
}
public interface IEcsModule
{
public void ImportSystems(EcsSystems.Builder builder);
}
public static class EcsSystemsExt
{
public static bool IsNullOrDestroyed(this EcsSystems self)
{
return self == null || self.IsDestoryed;
}
public static EcsSystems.Builder Add(this EcsSystems.Builder self, IEnumerable<IEcsSystem> range, object blockKey = null)
{
foreach (var item in range)
{
self.Add(item, blockKey);
}
return self;
}
}
}

11
src/EcsSystems.cs.meta Normal file
View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb5d6e45240ecad428d33758c4cc4c49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -21,9 +21,11 @@ namespace DCFApixels.DragonECS
#region Methods
public EcsPool<T> GetPool<T>() where T : struct;
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc;
public EcsFilter Filter<TInc>() where TInc : struct, IInc;
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc;
public ent NewEntity();
public bool EntityIsAlive(int entityID, short gen);
public ent GetEntity(int entityID);
public void DelEntity(int entityID);
public void Destroy();
@ -64,7 +66,7 @@ namespace DCFApixels.DragonECS
private EcsGroup _entities;
private short[] _gens;
private short[] _componentCounts;
//private short[] _componentCounts; //TODO
private IEcsPool[] _pools;
private EcsNullPool _nullPool;
@ -86,7 +88,8 @@ namespace DCFApixels.DragonECS
_entityDispenser = new IntDispenser();
_nullPool = new EcsNullPool(this);
_pools = new IEcsPool[512];
Array.Fill(_pools, _nullPool);
FillArray(_pools, _nullPool);
//Array.Fill(_pools, _nullPool); //TODO Fix it
_gens = new short[512];
_filters = new EcsFilter[64];
_entities = new EcsGroup(this, 512);
@ -104,7 +107,8 @@ namespace DCFApixels.DragonECS
{
int oldCapacity = _pools.Length;
Array.Resize(ref _pools, ComponentType.Capacity);
Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
FillArray(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
//Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); //TODO Fix it
Array.Resize(ref _filtersByIncludedComponents, ComponentType.Capacity);
Array.Resize(ref _filtersByExcludedComponents, ComponentType.Capacity);
@ -121,7 +125,7 @@ namespace DCFApixels.DragonECS
#region GetFilter
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
public EcsFilter Filter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc
{
var mask = EcsMaskMap<TArchetype>.GetMask<TInc, Exc>();
@ -277,19 +281,32 @@ namespace DCFApixels.DragonECS
}
#endregion
#region NewEntity/DelEntity
#region Entity
public ent NewEntity()
{
int entid = _entityDispenser.GetFree();
_entities.Add(entid);
if (_gens.Length < entid) Array.Resize(ref _gens, _gens.Length << 1);
return new ent(entid, _gens[entid]++, id);
int entityID = _entityDispenser.GetFree();
_entities.Add(entityID);
if (_gens.Length <= entityID)
Array.Resize(ref _gens, _gens.Length << 1);
return new ent(entityID, _gens[entityID]++, id);
}
public ent GetEntity(int entityID)
{
if (_entities.Contains(entityID) == false)
return ent.NULL;
return new ent(entityID, _gens[entityID], id);
}
public void DelEntity(int entityID)
{
_entityDispenser.Release(entityID);
_entities.Remove(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool EntityIsAlive(int entityID, short gen)
{
return _entities.Contains(entityID) && _gens[entityID] == gen;
}
#endregion
#region Destroy
@ -329,6 +346,22 @@ namespace DCFApixels.DragonECS
ComponentType.types[uniqueID] = typeof(T);
}
}
private void FillArray<T>(T[] array, T value, int startIndex = 0, int length = -1)
{
if (length < 0)
{
length = array.Length;
}
else
{
length = startIndex + length;
}
for (int i = startIndex; i < length; i++)
{
array[i] = value;
}
}
#endregion
}
}

View File

@ -5,52 +5,34 @@ using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS
{
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
// id - 32 bits
// gen - 16 bits
// world - 16 bits
[StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)]
public readonly struct ent : IEquatable<long>, IEquatable<ent>
{
public static readonly ent NULL = default;
// id - 32 bits
// gen - 16 bits
// world - 16 bits
public readonly long _full;
#region Properties
[EditorBrowsable(EditorBrowsableState.Never)]
public int id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (int)(_full >> 32);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public ushort gen
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (ushort)((_full << 32) >> 48);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public short world
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (short)((_full << 48) >> 48);
}
#endregion
[FieldOffset(0)]
private readonly long _full;
[FieldOffset(3)]
public readonly int id;
[FieldOffset(1)]
public readonly short gen;
[FieldOffset(0)]
public readonly short world;
#region Constructors
[EditorBrowsable(EditorBrowsableState.Never)]
public ent(int id, short gen, short world)
public ent(int id, short gen, short world): this()
{
_full = ((long)id) << 32;
_full += ((long)gen) << 16;
_full += world;
this.id = id;
this.gen = gen;
this.world = world;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ent(long value)
internal ent(long full) : this()
{
_full = value;
_full = full;
}
#endregion
@ -64,14 +46,9 @@ namespace DCFApixels.DragonECS
#region Equals
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(in ent other)
{
return _full == other._full;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is ent other && Equals(in other);
return obj is ent other && _full == other._full;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(ent other)
@ -85,26 +62,39 @@ namespace DCFApixels.DragonECS
}
#endregion
#region ToString
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => $"ent(id:{id} gen:{gen} world:{world})";
#endregion
#region operators
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(in ent left, in ent right) => left.Equals(in right);
public static bool operator ==(in ent a, in ent b) => a._full == b._full;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(in ent left, in ent right) => !left.Equals(in right);
public static bool operator !=(in ent a, in ent b) => a._full != b._full;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator long(in ent eent) => eent._full;
public static explicit operator long(in ent a) => a._full;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator int(in ent eent) => eent.id;
public static explicit operator int(in ent a) => a.id;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ent(in long value) => new ent(value);
public static explicit operator ent(in long a) => new ent(a);
#endregion
}
public static partial class entExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAlive(this ref ent self)
{
bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
if (!result) self = ent.NULL;
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNull(this in ent self)
{
@ -136,50 +126,4 @@ namespace DCFApixels.DragonECS
EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id);
}
}
public struct Entity
{
public IEcsWorld world;
public int id;
public Entity(IEcsWorld world, int id)
{
this.world = world;
this.id = id;
}
}
public static partial class EntityExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNull(this in Entity self)
{
return self.world == null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly T Read<T>(this in Entity self)
where T : struct
{
return ref self.world.GetPool<T>().Read(self.id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T Write<T>(this in Entity self)
where T : struct
{
return ref self.world.GetPool<T>().Write(self.id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Has<T>(this in Entity self)
where T : struct
{
return self.world.GetPool<T>().Has(self.id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Del<T>(this in Entity self)
where T : struct
{
self.world.GetPool<T>().Del(self.id);
}
}
}

View File

@ -7,8 +7,8 @@ namespace DCFApixels.DragonECS
public class EcsFrameworkException : Exception
{
public EcsFrameworkException() { }
public EcsFrameworkException(string message) : base(Exceptions.MESSAGE_SUFFIX + message) { }
public EcsFrameworkException(string message, Exception inner) : base(Exceptions.MESSAGE_SUFFIX + message, inner) { }
public EcsFrameworkException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsFrameworkException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsFrameworkException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -1,7 +0,0 @@
namespace DCFApixels.DragonECS
{
internal static class Exceptions
{
public const string MESSAGE_SUFFIX = "[DragonECS] ";
}
}

View File

@ -8,3 +8,9 @@ DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
// [EditorBrowsable(EditorBrowsableState.Never)]
//throw new EcsFrameworkException($"There is no suitable EcsRunner implementation for the {typeof(T).FullName} interface");

View File

@ -80,7 +80,7 @@ namespace DCFApixels.DragonECS
if (_count >= _dense.Length)
Array.Resize(ref _dense, _dense.Length << 1);
if (value > _sparse.Length)
if (value >= _sparse.Length)
{
int neadedSpace = _sparse.Length;
while (value >= neadedSpace)