update New/DelEntity add densify free entityIDs

This commit is contained in:
Mikhail 2024-02-14 01:04:22 +08:00
parent d1374d72ca
commit 94a99e3121
4 changed files with 50 additions and 37 deletions

View File

@ -189,11 +189,8 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Entity #region Entity
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ToSpan() #region New/Del
{
return _entityDispenser.UsedToEcsSpan(id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int NewEntity() public int NewEntity()
{ {
@ -201,15 +198,37 @@ namespace DCFApixels.DragonECS
int entityID = _entityDispenser.UseFree(); int entityID = _entityDispenser.UseFree();
_entitiesCount++; _entitiesCount++;
if (_gens.Length <= entityID) if (_entitesCapacity <= entityID)
{ {
Upsize_Internal(_gens.Length << 1); Upsize_Internal(_gens.Length << 1);
} }
_gens[entityID] &= GEN_BITS; _gens[entityID] &= GEN_MASK;
_entityListeners.InvokeOnNewEntity(entityID); _entityListeners.InvokeOnNewEntity(entityID);
return entityID; return entityID;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void NewEntity(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (IsUsed(entityID))
{
Throw.World_EntityIsAlreadyСontained(entityID);
}
#endif
unchecked { _version++; }
_entityDispenser.Use(entityID);
_entitiesCount++;
if (_entitesCapacity <= entityID)
{
Upsize_Internal(_gens.Length << 1);
}
_gens[entityID] &= GEN_MASK;
_entityListeners.InvokeOnNewEntity(entityID);
}
public entlong NewEntityLong() public entlong NewEntityLong()
{ {
int e = NewEntity(); int e = NewEntity();
@ -238,6 +257,14 @@ namespace DCFApixels.DragonECS
_entitiesCount--; _entitiesCount--;
_entityListeners.InvokeOnDelEntity(entityID); _entityListeners.InvokeOnDelEntity(entityID);
} }
#endregion
#region Other
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ToSpan()
{
return _entityDispenser.UsedToEcsSpan(id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe entlong GetEntityLong(int entityID) public unsafe entlong GetEntityLong(int entityID)
{ {
@ -282,6 +309,11 @@ namespace DCFApixels.DragonECS
} }
} }
} }
//public void Densify()
//{
// _entityDispenser.Sort();
//}
#endregion
#region Copy/Clone #region Copy/Clone
public void CopyEntity(int fromEntityID, int toEntityID) public void CopyEntity(int fromEntityID, int toEntityID)
@ -374,6 +406,7 @@ namespace DCFApixels.DragonECS
unchecked { _gens[e]++; }//up gen unchecked { _gens[e]++; }//up gen
_gens[e] |= DEATH_GEN_BIT; _gens[e] |= DEATH_GEN_BIT;
} }
_entityDispenser.Sort(); //уплотнение свободных айдишников
} }
#endregion #endregion

View File

@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS
} }
public abstract partial class EcsWorld public abstract partial class EcsWorld
{ {
private const short GEN_BITS = 0x7fff; private const short GEN_MASK = 0x7fff;
private const short DEATH_GEN_BIT = short.MinValue; private const short DEATH_GEN_BIT = short.MinValue;
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5; private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5;
private const int DEL_ENT_BUFFER_MIN_SIZE = 64; private const int DEL_ENT_BUFFER_MIN_SIZE = 64;

View File

@ -83,7 +83,11 @@ namespace DCFApixels.DragonECS.Internal
{ {
throw new EcsFrameworkException($"An entity with identifier {entityID} is not contained in this world"); throw new EcsFrameworkException($"An entity with identifier {entityID} is not contained in this world");
} }
[MethodImpl(MethodImplOptions.NoInlining)]
public static void World_EntityIsAlreadyСontained(int entityID)
{
throw new EcsFrameworkException($"An entity with identifier {entityID} is already contained in this world");
}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Ent_ThrowIsNotAlive(entlong entity) internal static void Ent_ThrowIsNotAlive(entlong entity)
@ -109,7 +113,6 @@ namespace DCFApixels.DragonECS
public EcsFrameworkException() { } public EcsFrameworkException() { }
public EcsFrameworkException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { } public EcsFrameworkException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsFrameworkException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { } public EcsFrameworkException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsFrameworkException(SerializationInfo info, StreamingContext context) : base(info, context) { }
} }
[Serializable] [Serializable]
public class EcsRunnerImplementationException : EcsFrameworkException public class EcsRunnerImplementationException : EcsFrameworkException
@ -117,6 +120,5 @@ namespace DCFApixels.DragonECS
public EcsRunnerImplementationException() { } public EcsRunnerImplementationException() { }
public EcsRunnerImplementationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { } public EcsRunnerImplementationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsRunnerImplementationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { } public EcsRunnerImplementationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsRunnerImplementationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
} }
} }

View File

@ -13,14 +13,13 @@ namespace DCFApixels.DragonECS.Utils
{ {
private const int FREE_FLAG_BIT = ~INDEX_MASK; private const int FREE_FLAG_BIT = ~INDEX_MASK;
private const int INDEX_MASK = 0x7FFF_FFFF; private const int INDEX_MASK = 0x7FFF_FFFF;
private const int MIN_SIZE = 4; private const int MIN_SIZE = 4;
private int[] _dense = Array.Empty<int>(); private int[] _dense = Array.Empty<int>();
private int[] _sparse = Array.Empty<int>(); //hibit free flag private int[] _sparse = Array.Empty<int>(); //hibit free flag
private int _usedCount; //[|uuuu| ] private int _usedCount; //[uuuu| ]
private int _size; //[|uuuu|ffffff] private int _size; //[uuuu|ffffff]
private int _nullID; private int _nullID;
@ -312,27 +311,6 @@ namespace DCFApixels.DragonECS.Utils
} }
#endregion #endregion
#region Spans
public readonly struct UsedSpan : IEnumerable<int>
{
private readonly IdDispenser _instance;
public int Count => _instance._usedCount;
internal UsedSpan(IdDispenser instance) => _instance = instance;
public Enumerator GetEnumerator() => new Enumerator(_instance._dense, 0, _instance._usedCount);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public readonly struct FreeSpan : IEnumerable<int>
{
private readonly IdDispenser _instance;
public int Count => _instance._size - _instance._usedCount;
internal FreeSpan(IdDispenser instance) => _instance = instance;
public Enumerator GetEnumerator() => new Enumerator(_instance._dense, _instance._usedCount, Count);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
#endregion
#region Utils #region Utils
private enum IDState : byte private enum IDState : byte
{ {
@ -340,7 +318,6 @@ namespace DCFApixels.DragonECS.Utils
Reserved = 1, Reserved = 1,
Used = 2, Used = 2,
} }
private static class ThrowHalper private static class ThrowHalper
{ {
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
@ -361,7 +338,7 @@ namespace DCFApixels.DragonECS.Utils
public static void UndefinedException() { throw new Exception(); } public static void UndefinedException() { throw new Exception(); }
} }
internal class DebuggerProxy private class DebuggerProxy
{ {
private IdDispenser _target; private IdDispenser _target;
public DebuggerProxy(IdDispenser dispenser) public DebuggerProxy(IdDispenser dispenser)
@ -370,6 +347,7 @@ namespace DCFApixels.DragonECS.Utils
} }
#if DEBUG #if DEBUG
public ReadOnlySpan<int> Used => new ReadOnlySpan<int>(_target._dense, 0, _target._usedCount); public ReadOnlySpan<int> Used => new ReadOnlySpan<int>(_target._dense, 0, _target._usedCount);
public ReadOnlySpan<int> Free => new ReadOnlySpan<int>(_target._dense, _target._usedCount, _target._size - _target._usedCount);
public Pair[] Pairs public Pair[] Pairs
{ {
get get