add EcsWorldConfig

This commit is contained in:
Mikhail 2024-02-03 01:12:53 +08:00
parent df24a2d26a
commit a248f4fc34
10 changed files with 218 additions and 44 deletions

View File

@ -1,5 +1,13 @@
namespace DCFApixels.DragonECS
{
public sealed class EcsDefaultWorld : EcsWorld { }
public sealed class EcsEventWorld : EcsWorld { }
public sealed class EcsDefaultWorld : EcsWorld
{
public EcsDefaultWorld() : base(null) { }
public EcsDefaultWorld(IEcsWorldConfig config) : base(config) { }
}
public sealed class EcsEventWorld : EcsWorld
{
public EcsEventWorld() : base(null) { }
public EcsEventWorld(IEcsWorldConfig config) : base(config) { }
}
}

View File

@ -74,7 +74,7 @@ namespace DCFApixels.DragonECS
static EcsComponentCopyHandler()
{
T def = default;
if(def is IEcsComponentCopy<T> intrf)
if (def is IEcsComponentCopy<T> intrf)
{
instance = intrf;
}

View File

@ -41,6 +41,11 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v);
public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v);
public static void PrintErrorAndBreak(object v)
{
Print(EcsConsts.DEBUG_ERROR_TAG, v);
Break();
}
public static void PrintPass(object v) => Print(EcsConsts.DEBUG_PASS_TAG, v);
public static void Print()
{

View File

@ -3,12 +3,14 @@ using DCFApixels.DragonECS.Utils;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using static Leopotam.EcsLite.EcsWorld;
namespace DCFApixels.DragonECS
{
public abstract partial class EcsWorld
{
public readonly short id;
private IEcsWorldConfig _config;
private bool _isDestroyed;
@ -36,6 +38,11 @@ namespace DCFApixels.DragonECS
private readonly PoolsMediator _poolsMediator;
#region Properties
public IEcsWorldConfig Config
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _config; }
}
public bool IsDestroyed
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -63,7 +70,7 @@ namespace DCFApixels.DragonECS
get { return _isEnableAutoReleaseDelEntBuffer; }
}
public EcsReadonlyGroup Entities
public EcsReadonlyGroup Entities
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@ -84,13 +91,15 @@ namespace DCFApixels.DragonECS
#endregion
#region Constructors/Destroy
public EcsWorld() : this(true) { }
internal EcsWorld(bool isIndexable)
public EcsWorld(IEcsWorldConfig config) : this(config, true) { }
private EcsWorld(IEcsWorldConfig config, bool isIndexable)
{
const int POOLS_CAPACITY = 512;
_poolsMediator = new PoolsMediator(this);
_entitesCapacity = 512;
if (config == null)
{
config = EmptyConfig.Instance;
}
config.Lock();
_config = config;
if (isIndexable)
{
@ -102,13 +111,15 @@ namespace DCFApixels.DragonECS
Worlds[id] = this;
}
_poolsMediator = new PoolsMediator(this);
_entityDispenser = new IntDispenser(0);
_pools = new IEcsPoolImplementation[POOLS_CAPACITY];
_poolComponentCounts = new int[POOLS_CAPACITY];
//_sortedPoolIds = new int[POOLS_CAPACITY];
//_sortedPoolIdsMapping = new int[POOLS_CAPACITY];
int poolsCapacity = config.Get_PoolsCapacity();
_pools = new IEcsPoolImplementation[poolsCapacity];
_poolComponentCounts = new int[poolsCapacity];
ArrayUtility.Fill(_pools, _nullPool);
_entitesCapacity = config.Get_EntitiesCapacity();
_gens = new short[_entitesCapacity];
_componentCounts = new short[_entitesCapacity];
@ -116,9 +127,11 @@ namespace DCFApixels.DragonECS
_delEntBufferCount = 0;
_delEntBuffer = new int[_entitesCapacity];
_entitiesComponentMasks = new int[_entitesCapacity][];
int maskLength = _pools.Length / 32 + 1;
for (int i = 0; i < _entitesCapacity; i++)
{
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1];
_entitiesComponentMasks[i] = new int[maskLength];
}
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
@ -264,7 +277,9 @@ namespace DCFApixels.DragonECS
_entitiesCount++;
if (_gens.Length <= entityID)
Upsize();
{
Upsize(_gens.Length << 1);
}
_gens[entityID] &= GEN_BITS;
_allEntites.Add(entityID);
@ -432,24 +447,31 @@ namespace DCFApixels.DragonECS
#region Upsize
[MethodImpl(MethodImplOptions.NoInlining)]
private void Upsize()
public void Upsize(int minSize)
{
Array.Resize(ref _gens, _gens.Length << 1);
Array.Resize(ref _componentCounts, _gens.Length);
Array.Resize(ref _delEntBuffer, _gens.Length);
Array.Resize(ref _entitiesComponentMasks, _gens.Length);
for (int i = _entitesCapacity; i < _gens.Length; i++)
if (minSize < Capacity)
{
return;
}
int newSize = 1 << (BitsUtility.GetHighBitNumber(minSize - 1) + 1);
Array.Resize(ref _gens, newSize);
Array.Resize(ref _componentCounts, newSize);
Array.Resize(ref _delEntBuffer, newSize);
Array.Resize(ref _entitiesComponentMasks, newSize);
for (int i = _entitesCapacity; i < newSize; i++)
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1];
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
_entitesCapacity = _gens.Length;
_entitesCapacity = newSize;
for (int i = 0; i < _groups.Count; i++)
{
if (_groups[i].TryGetTarget(out EcsGroup group))
{
group.OnWorldResize(_gens.Length);
group.OnWorldResize(newSize);
}
else
{
@ -459,9 +481,11 @@ namespace DCFApixels.DragonECS
}
}
foreach (var item in _pools)
item.OnWorldResize(_gens.Length);
{
item.OnWorldResize(newSize);
}
_listeners.InvokeOnWorldResize(_gens.Length);
_listeners.InvokeOnWorldResize(newSize);
}
#endregion
@ -538,6 +562,21 @@ namespace DCFApixels.DragonECS
}
}
#endregion
#region EmptyConfig
private class EmptyConfig : IEcsWorldConfig
{
public static readonly EmptyConfig Instance = new EmptyConfig();
private EmptyConfig() { }
public bool IsLocked => true;
public T Get<T>(string valueName) { return default; }
public bool Has(string valueName) { return false; }
public void Lock() { }
public void Remove(string valueName) { }
public void Set<T>(string valueName, T value) { }
public bool TryGet<T>(string valueName, out T value) { value = default; return false; }
}
#endregion
}
#region Callbacks Interface
@ -589,4 +628,4 @@ namespace DCFApixels.DragonECS
public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self);
}
#endregion
}
}

View File

@ -25,7 +25,7 @@ namespace DCFApixels.DragonECS
public bool IsComponentTypeDeclared(Type type) => _componentIds.Contains(EcsTypeCode.Get(type));
public bool IsComponentTypeDeclared(int componentTypeID)
{
if(componentTypeID >= 0 && componentTypeID < _pools.Length)
if (componentTypeID >= 0 && componentTypeID < _pools.Length)
{
return _pools[componentTypeID] != _nullPool;
}

View File

@ -22,14 +22,14 @@ namespace DCFApixels.DragonECS
private const int DEL_ENT_BUFFER_MIN_SIZE = 64;
private static EcsWorld[] Worlds = new EcsWorld[4];
private static IdDispenser _worldIdDispenser = new IdDispenser(0);
private static IdDispenser _worldIdDispenser = new IdDispenser(4);
private static List<DataReleaser> _dataReleaseres = new List<DataReleaser>();
//public static int Copacity => Worlds.Length;
static EcsWorld()
{
Worlds[0] = new EcsNullWorld();
Worlds[0] = new NullWorld();
}
private static void ReleaseData(int worldID)
{
@ -121,9 +121,9 @@ namespace DCFApixels.DragonECS
}
}
}
}
internal sealed class EcsNullWorld : EcsWorld
{
internal EcsNullWorld() : base(false) { }
private sealed class NullWorld : EcsWorld
{
internal NullWorld() : base(EmptyConfig.Instance, false) { }
}
}
}

124
src/EcsWorldConfig.cs Normal file
View File

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public interface IEcsWorldConfig
{
bool IsLocked { get; }
void Lock();
void Set<T>(string valueName, T value);
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
void Remove(string valueName);
}
public class EcsWorldConfig : IEcsWorldConfig
{
private Dictionary<string, object> _storage = new Dictionary<string, object>();
private bool _isLocked = false;
public bool IsLocked { get { return _isLocked; } }
public void Lock()
{
_isLocked = true;
}
public T Get<T>(string valueName)
{
return (T)_storage[valueName];
}
public bool Has(string valueName)
{
return _storage.ContainsKey(valueName);
}
public void Remove(string valueName)
{
_storage.Remove(valueName);
}
public void Set<T>(string valueName, T value)
{
if (_isLocked)
{
throw new InvalidOperationException();
}
_storage[valueName] = value;
}
public bool TryGet<T>(string valueName, out T value)
{
bool result = _storage.TryGetValue(valueName, out object rawValue);
value = rawValue == null ? default : (T)rawValue;
return result;
}
}
public static class EcsWorldConfigExtensions
{
public static T GetOrDefault<T>(this IEcsWorldConfig self, string valueName, T defaultValue)
{
if (self.TryGet(valueName, out T value))
{
return value;
}
return defaultValue;
}
private const string ENTITIES_CAPACITY = nameof(ENTITIES_CAPACITY);
private const int ENTITIES_CAPACITY_DEFAULT = 512;
public static TConfig Set_EntitiesCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(ENTITIES_CAPACITY, value);
return self;
}
public static int Get_EntitiesCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(ENTITIES_CAPACITY, ENTITIES_CAPACITY_DEFAULT);
}
//private const string RECYCLED_ENTITIES_CAPACITY = nameof(RECYCLED_ENTITIES_CAPACITY);
//public static void Set_RecycledEntitiesCapacity(this IEcsWorldConfig self, int value)
//{
// self.Set(RECYCLED_ENTITIES_CAPACITY, value);
//}
//public static int Get_RecycledEntitiesCapacity(this IEcsWorldConfig self)
//{
// return self.GetOrDefault(RECYCLED_ENTITIES_CAPACITY, self.Get_EntitiesCapacity() / 2);
//}
private const string POOLS_CAPACITY = nameof(POOLS_CAPACITY);
private const int POOLS_CAPACITY_DEFAULT = 512;
public static TConfig Set_PoolsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(POOLS_CAPACITY, value);
return self;
}
public static int Get_PoolsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(POOLS_CAPACITY, POOLS_CAPACITY_DEFAULT);
}
private const string COMPONENT_POOL_CAPACITY = nameof(COMPONENT_POOL_CAPACITY);
private const int COMPONENT_POOL_CAPACITY_DEFAULT = 512;
public static TConfig Set_PoolComponentsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(COMPONENT_POOL_CAPACITY, value);
return self;
}
public static int Get_PoolComponentsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(COMPONENT_POOL_CAPACITY, COMPONENT_POOL_CAPACITY_DEFAULT);
}
private const string POOL_RECYCLED_COMPONENTS_CAPACITY = nameof(POOL_RECYCLED_COMPONENTS_CAPACITY);
public static TConfig Set_PoolRecycledComponentsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(POOL_RECYCLED_COMPONENTS_CAPACITY, value);
return self;
}
public static int Get_PoolRecycledComponentsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(POOL_RECYCLED_COMPONENTS_CAPACITY, self.Get_PoolComponentsCapacity() / 2);
}
}
}

View File

@ -143,12 +143,10 @@ namespace DCFApixels.DragonECS
_componentTypeID = componentTypeID;
_maskBit = EcsMaskChunck.FromID(componentTypeID);
const int capacity = 512;
_mapping = new int[world.Capacity];
_recycledItems = new int[128];
_recycledItems = new int[world.Config.Get_PoolRecycledComponentsCapacity()];
_recycledItemsCount = 0;
_items = new T[capacity];
_items = new T[world.Config.Get_PoolComponentsCapacity()];
_itemsCount = 0;
}
void IEcsPoolImplementation.OnWorldResize(int newSize)

View File

@ -81,6 +81,11 @@ namespace DCFApixels.DragonECS.Internal
else
throw new EcsFrameworkException($"The {entity} is not alive.");
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void UndefinedException()
{
throw new Exception();
}
}
}

View File

@ -14,12 +14,7 @@ namespace DCFApixels.DragonECS.Utils
#endregion
#region Constructor
public IntDispenser()
{
_freeInts = new ConcurrentQueue<int>();
_increment = 0;
}
public IntDispenser(int startIncrement)
public IntDispenser(int startIncrement = 0)
{
_freeInts = new ConcurrentQueue<int>();
_increment = startIncrement;