diff --git a/src/EcsMask.cs b/src/EcsMask.cs index 3a88fdc..fcc4220 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -962,29 +962,30 @@ namespace DCFApixels.DragonECS.Internal internal const int STACK_BUFFER_THRESHOLD = 100; [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void ConvertToChuncks(EcsMaskChunck* ptr, UnsafeArray input, UnsafeArray output) + internal static void ConvertToChuncks(EcsMaskChunck* bufferPtr, UnsafeArray input, UnsafeArray output) { for (int i = 0; i < input.Length; i++) { - ptr[i] = EcsMaskChunck.FromID(input.ptr[i]); + bufferPtr[i] = EcsMaskChunck.FromID(input.ptr[i]); } - for (int inputI = 0, outputI = 0; outputI < output.Length; inputI++, ptr++) + for (int inputI = 0, outputI = 0; outputI < output.Length; inputI++, bufferPtr++) { - int maskX = ptr->mask; - if (maskX == 0) { continue; } - int chunkIndexX = ptr->chunkIndex; + int stackingMask = bufferPtr->mask; + if (stackingMask == 0) { continue; } + int stackingChunkIndex = bufferPtr->chunkIndex; - EcsMaskChunck* subptr = ptr; - for (int j = 1; j < input.Length - inputI; j++, subptr++) + EcsMaskChunck* bufferSpanPtr = bufferPtr + 1; + for (int j = 1; j < input.Length - inputI; j++, bufferSpanPtr++) { - if (subptr->chunkIndex == chunkIndexX) + if (bufferSpanPtr->chunkIndex == stackingChunkIndex) { - maskX |= subptr->mask; - *subptr = default; + stackingMask |= bufferSpanPtr->mask; + *bufferSpanPtr = default; } } - output.ptr[outputI] = new EcsMaskChunck(chunkIndexX, maskX); + + output.ptr[outputI] = new EcsMaskChunck(stackingChunkIndex, stackingMask); outputI++; } } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index fa2cae6..f440b2b 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -365,6 +365,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public int NewEntity(int entityID) { + _entityDispenser.Upsize(entityID + 1); #if DEBUG if (IsUsed(entityID)) { Throw.World_EntityIsAlreadyСontained(entityID); } #elif DRAGONECS_STABILITY_MODE @@ -1257,9 +1258,12 @@ namespace DCFApixels.DragonECS { EntitySlotInfo[] result = new EntitySlotInfo[_world.Count]; int i = 0; - foreach (var e in _world.ToSpan()) + using (_world.DisableAutoReleaseDelEntBuffer()) { - result[i++] = _world.GetEntitySlotInfoDebug(e); + foreach (var e in _world.ToSpan()) + { + result[i++] = _world.GetEntitySlotInfoDebug(e); + } } return result; } diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index 9c88512..66d84d7 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -91,10 +91,22 @@ namespace DCFApixels.DragonECS.Internal Execute_Iternal(); #if DEBUG || DRAGONECS_DEEP_DEBUG var newSpan = new EcsSpan(World.ID, _filteredAllEntities, _filteredAllEntitiesCount); - foreach (var e in newSpan) + using (EcsGroup group = EcsGroup.New(World)) { - if (World.IsMatchesMask(Mask, e) == false) + foreach (var e in World.Entities) { + if (World.IsMatchesMask(Mask, e)) + { + group.Add(e); + } + } + + if (group.SetEquals(newSpan) == false) + { + int[] array = new int[_filteredAllEntities.Length]; + var count = _iterator.IterateTo(World.Entities, ref array); + + EcsDebug.PrintError(newSpan.ToString() + "\r\n" + group.ToSpan().ToString()); Throw.DeepDebugException(); } } diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 655e44a..90980b9 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -95,11 +95,12 @@ namespace DCFApixels.DragonECS { ref int itemIndex = ref _mapping[entityID]; #if DEBUG + if (_source.IsUsed(entityID) == false) { Throw.Ent_ThrowIsNotAlive(_source, entityID); } if (itemIndex > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent(entityID); } if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } #elif DRAGONECS_STABILITY_MODE if (itemIndex > 0) { return ref Get(entityID); } - if (_isLocked) { return ref _items[0]; } + if (_isLocked | _source.IsUsed(entityID) == false) { return ref _items[0]; } #endif if (_recycledItemsCount > 0) { diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 1bec619..72100cc 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -104,10 +104,11 @@ namespace DCFApixels.DragonECS public void Add(int entityID) { #if DEBUG + if (_source.IsUsed(entityID) == false) { Throw.Ent_ThrowIsNotAlive(_source, entityID); } if (Has(entityID)) { EcsPoolThrowHelper.ThrowAlreadyHasComponent(entityID); } if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } #elif DRAGONECS_STABILITY_MODE - if (Has(entityID) || _isLocked) { return; } + if (Has(entityID) | _source.IsUsed(entityID) == false | _isLocked) { return; } #endif _count++; _mapping[entityID] = true; diff --git a/src/Utils/Exceptions.cs b/src/Utils/Exceptions.cs index ef53bf6..d4086a3 100644 --- a/src/Utils/Exceptions.cs +++ b/src/Utils/Exceptions.cs @@ -118,6 +118,11 @@ namespace DCFApixels.DragonECS.Internal throw new InvalidOperationException($"The method {methodName} can only be executed before creating entities in the world."); } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Ent_ThrowIsNotAlive(EcsWorld world, int entityID) + { + Ent_ThrowIsNotAlive((world, entityID)); + } [MethodImpl(MethodImplOptions.NoInlining)] internal static void Ent_ThrowIsNotAlive(entlong entity) {