diff --git a/DragonECS.csproj b/DragonECS.csproj
index 41358e5..ab300ab 100644
--- a/DragonECS.csproj
+++ b/DragonECS.csproj
@@ -10,7 +10,7 @@
DCFApixels.DragonECS
DragonECS
- 0.9.9
+ 0.9.10
DCFApixels
ECS Framework for Game Engines with C# and .Net Platform
DCFApixels
diff --git a/package.json b/package.json
index fcffa56..bc71101 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"displayName": "DragonECS",
"description": "C# Entity Component System Framework",
"unity": "2020.3",
- "version": "0.9.9",
+ "version": "0.9.10",
"repository": {
"type": "git",
"url": "https://github.com/DCFApixels/DragonECS.git"
diff --git a/src/Collections/EcsGroup.cs b/src/Collections/EcsGroup.cs
index 5d70cfe..997b4ce 100644
--- a/src/Collections/EcsGroup.cs
+++ b/src/Collections/EcsGroup.cs
@@ -1,6 +1,7 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using System;
using System.Collections;
diff --git a/src/Collections/EcsSpan.cs b/src/Collections/EcsSpan.cs
index 48c26c4..11161e6 100644
--- a/src/Collections/EcsSpan.cs
+++ b/src/Collections/EcsSpan.cs
@@ -1,6 +1,7 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using System;
using System.Collections.Generic;
diff --git a/src/DebugUtils/EcsDebug.cs b/src/DebugUtils/EcsDebug.cs
index 0f5608e..e128b0a 100644
--- a/src/DebugUtils/EcsDebug.cs
+++ b/src/DebugUtils/EcsDebug.cs
@@ -247,7 +247,7 @@ namespace DCFApixels.DragonECS
#region Static Constructor
static DebugService()
{
-#if !UNITY_5_3_OR_NEWER
+#if UNITY_5_3_OR_NEWER
Set(new NullDebugService());
#else
Set(new DefaultDebugService());
diff --git a/src/DebugUtils/MetaAttributes/MetaIDAttribute.cs b/src/DebugUtils/MetaAttributes/MetaIDAttribute.cs
index c42f9bf..22ef974 100644
--- a/src/DebugUtils/MetaAttributes/MetaIDAttribute.cs
+++ b/src/DebugUtils/MetaAttributes/MetaIDAttribute.cs
@@ -185,7 +185,7 @@ namespace DCFApixels.DragonECS
public bool IsCollidingID(string id)
{
- if(_collidingIDs== null)
+ if (_collidingIDs == null)
{
return false;
}
diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs
index f440b2b..35ca962 100644
--- a/src/EcsWorld.cs
+++ b/src/EcsWorld.cs
@@ -2,6 +2,7 @@
#undef DEBUG
#endif
using DCFApixels.DragonECS.Core;
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.PoolsCore;
using System;
@@ -440,7 +441,7 @@ namespace DCFApixels.DragonECS
{
for (int i = _emptyEntitiesCount - 1; i >= 0; i--)
{
- if(_emptyEntities[i] == entityID)
+ if (_emptyEntities[i] == entityID)
{
_emptyEntities[i] = _emptyEntities[--_emptyEntitiesCount];
return true;
@@ -856,7 +857,7 @@ namespace DCFApixels.DragonECS
}
_emptyEntitiesCount = 0;
- if(count < 0)
+ if (count < 0)
{
count = _delEntBufferCount;
}
diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs
index d2216d5..404bc3f 100644
--- a/src/EcsWorld.pools.cs
+++ b/src/EcsWorld.pools.cs
@@ -314,7 +314,7 @@ namespace DCFApixels.DragonECS
slot.count++;
slot.version++;
var count = _entities[entityID].componentsCount++;
- if(count == 0 && IsUsed(entityID))
+ if (count == 0 && IsUsed(entityID))
{
RemoveFromEmptyEntities(entityID);
}
diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs
index 9d3b3f9..2d6b980 100644
--- a/src/EcsWorld.static.cs
+++ b/src/EcsWorld.static.cs
@@ -45,10 +45,15 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGetWorld(short worldID, out EcsWorld world)
{// ts
+ if (worldID >= _worlds.Length)
+ {
+ world = null;
+ return false;
+ }
world = _worlds[worldID];
return
world != null &&
- world.IsDestroyed != false &&
+ world.IsDestroyed == false &&
worldID != 0;
}
diff --git a/src/Executors/EcsWhereToGroupExecutor.cs b/src/Executors/EcsWhereToGroupExecutor.cs
index 8d57c6e..ed6b6b6 100644
--- a/src/Executors/EcsWhereToGroupExecutor.cs
+++ b/src/Executors/EcsWhereToGroupExecutor.cs
@@ -69,19 +69,19 @@ namespace DCFApixels.DragonECS.Internal
_version++;
_iterator.IterateTo(World.Entities, _filteredAllGroup);
#if DEBUG && DRAGONECS_DEEP_DEBUG
- if(_filteredGroup == null)
+ if (_filteredGroup == null)
{
_filteredGroup = EcsGroup.New(World);
}
_filteredGroup.Clear();
foreach (var e in World.Entities)
{
- if(World.IsMatchesMask(Mask, e))
+ if (World.IsMatchesMask(Mask, e))
{
_filteredGroup.Add(e);
}
}
- if(_filteredAllGroup.SetEquals(_filteredGroup) == false)
+ if (_filteredAllGroup.SetEquals(_filteredGroup) == false)
{
throw new System.InvalidOperationException();
}
diff --git a/src/Executors/MaskQueryExecutor.cs b/src/Executors/MaskQueryExecutor.cs
index 5676805..c7c53c4 100644
--- a/src/Executors/MaskQueryExecutor.cs
+++ b/src/Executors/MaskQueryExecutor.cs
@@ -125,7 +125,7 @@ namespace DCFApixels.DragonECS.Core
_maskInc = mask._incs;
_maskExc = mask._excs;
_count = 1 + mask._incs.Length + mask._excs.Length;
-
+
_versions = UnmanagedArrayUtility.NewAndInit(_count);
}
public bool Check()
diff --git a/src/Internal/BitsUtility.cs b/src/Internal/BitsUtility.cs
index 87c9674..c79115e 100644
--- a/src/Internal/BitsUtility.cs
+++ b/src/Internal/BitsUtility.cs
@@ -538,7 +538,7 @@ namespace DCFApixels.DragonECS.Internal
state ^= state >> 17;
state ^= state << 5;
return state;
- };
+ }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long NextXorShiftState(long state)
diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs
index 90980b9..375257a 100644
--- a/src/Pools/EcsPool.cs
+++ b/src/Pools/EcsPool.cs
@@ -95,6 +95,7 @@ namespace DCFApixels.DragonECS
{
ref int itemIndex = ref _mapping[entityID];
#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (_source.IsUsed(entityID) == false) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (itemIndex > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent(entityID); }
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
@@ -144,6 +145,9 @@ namespace DCFApixels.DragonECS
}
public ref T TryAddOrGet(int entityID)
{
+#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
+#endif
ref int itemIndex = ref _mapping[entityID];
if (itemIndex <= 0)
{ //Add block
@@ -185,6 +189,7 @@ namespace DCFApixels.DragonECS
{
ref int itemIndex = ref _mapping[entityID];
#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (itemIndex <= 0) { EcsPoolThrowHelper.ThrowNotHaveComponent(entityID); }
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
#elif DRAGONECS_STABILITY_MODE
@@ -237,9 +242,8 @@ namespace DCFApixels.DragonECS
#elif DRAGONECS_STABILITY_MODE
if (_isLocked) { return; }
#endif
- _recycledItemsCount = 0; // , Del
+ _recycledItemsCount = 0; // , Del
if (_itemsCount <= 0) { return; }
- _itemsCount = 0;
var span = _source.Where(out SingleAspect _);
foreach (var entityID in span)
{
@@ -251,6 +255,8 @@ namespace DCFApixels.DragonECS
_listeners.InvokeOnDel(entityID, _listenersCachedCount);
#endif
}
+ _itemsCount = 0;
+ _recycledItemsCount = 0;
}
#endregion
@@ -447,7 +453,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveListener(IEcsPoolEventListener listener) { _pool.AddListener(listener); }
#endif
-#endregion
+ #endregion
#region Convertors
public static implicit operator ReadonlyEcsPool(EcsPool a) { return new ReadonlyEcsPool(a); }
diff --git a/src/Utils/Uncheked.meta b/src/Utils/Uncheked.meta
new file mode 100644
index 0000000..af73cfd
--- /dev/null
+++ b/src/Utils/Uncheked.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5f2e943735300fe40bdbff86b6089dad
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/src/Utils/Uncheked/EntitiesMatrix.cs b/src/Utils/Uncheked/EntitiesMatrix.cs
new file mode 100644
index 0000000..75baf56
--- /dev/null
+++ b/src/Utils/Uncheked/EntitiesMatrix.cs
@@ -0,0 +1,44 @@
+#if DISABLE_DEBUG
+#undef DEBUG
+#endif
+
+namespace DCFApixels.DragonECS.UncheckedCore
+{
+ public readonly struct EntitiesMatrix
+ {
+ private readonly EcsWorld _world;
+ public EntitiesMatrix(EcsWorld world)
+ {
+ _world = world;
+ }
+ public int PoolsCount
+ {
+ get { return _world.PoolsCount; }
+ }
+ public int EntitesCount
+ {
+ get { return _world.Capacity; }
+ }
+ public int GetEntityComponentsCount(int entityID)
+ {
+ return _world.GetComponentsCount(entityID);
+ }
+ public int GetEntityGen(int entityID)
+ {
+ return _world.GetGen(entityID);
+ }
+ public bool IsEntityUsed(int entityID)
+ {
+ return _world.IsUsed(entityID);
+ }
+ public bool this[int entityID, int poolID]
+ {
+ get
+ {
+ int entityStartChunkIndex = entityID << _world._entityComponentMaskLengthBitShift;
+ var chunkInfo = EcsMaskChunck.FromID(poolID);
+ return (_world._entityComponentMasks[entityStartChunkIndex + chunkInfo.chunkIndex] & chunkInfo.mask) != 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Utils/Uncheked/EntitiesMatrix.cs.meta b/src/Utils/Uncheked/EntitiesMatrix.cs.meta
new file mode 100644
index 0000000..3f9b8a8
--- /dev/null
+++ b/src/Utils/Uncheked/EntitiesMatrix.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 82a4a05728fb81b4b903d9893a85f77f
\ No newline at end of file
diff --git a/src/Utils/Uncheked/EntitySlotInfo.cs b/src/Utils/Uncheked/EntitySlotInfo.cs
new file mode 100644
index 0000000..942d666
--- /dev/null
+++ b/src/Utils/Uncheked/EntitySlotInfo.cs
@@ -0,0 +1,137 @@
+#if DISABLE_DEBUG
+#undef DEBUG
+#endif
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace DCFApixels.DragonECS.Core.Unchecked
+{
+ [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)]
+ [DebuggerTypeProxy(typeof(EntityDebuggerProxy))]
+ public struct EntitySlotInfo : IEquatable
+ {
+#if UNITY_EDITOR
+ [UnityEngine.SerializeField]
+#endif
+ [FieldOffset(0)]
+ public long full; //Union
+ [FieldOffset(0), NonSerialized]
+ public int id;
+ [FieldOffset(4), NonSerialized]
+ public short gen;
+ [FieldOffset(6), NonSerialized]
+ public short worldID;
+
+ #region Properties
+ public EcsWorld World { get { return EcsWorld.GetWorld(worldID); } }
+ public StateFlag State { get { return full == 0 ? StateFlag.Null : World.IsAlive(id, gen) ? StateFlag.Alive : StateFlag.Dead; } }
+ #endregion
+
+ #region Constructors/Deconstructors
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public EntitySlotInfo(long full) : this()
+ {
+ this.full = full;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public EntitySlotInfo(int id, short gen, short world) : this()
+ {
+ this.id = id;
+ this.gen = gen;
+ worldID = world;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Deconstruct(out int id, out int gen, out int worldID)
+ {
+ id = this.id;
+ gen = this.gen;
+ worldID = this.worldID;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Deconstruct(out int id, out int worldID)
+ {
+ id = this.id;
+ worldID = this.worldID;
+ }
+ #endregion
+
+ #region Operators
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(EntitySlotInfo a, EntitySlotInfo b) { return a.full == b.full; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(EntitySlotInfo a, EntitySlotInfo b) { return a.full != b.full; }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator EntitySlotInfo(entlong a) { return new EntitySlotInfo(a._full); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator entlong(EntitySlotInfo a) { return new entlong(a.full); }
+ #endregion
+
+ #region Other
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override int GetHashCode() { return unchecked(id ^ gen ^ (worldID * EcsConsts.MAGIC_PRIME)); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString() { return $"slot(id:{id} g:{gen} w:{worldID} {(State == StateFlag.Null ? "null" : State == StateFlag.Alive ? "alive" : "not alive")})"; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object obj) { return obj is EntitySlotInfo other && this == other; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(EntitySlotInfo other) { return this == other; }
+
+ public enum StateFlag { Null, Dead, Alive, }
+ #endregion
+ }
+
+
+
+ internal class EntityDebuggerProxy
+ {
+ private List