mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
add EcsWorldConfig
This commit is contained in:
parent
df24a2d26a
commit
a248f4fc34
@ -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) { }
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
124
src/EcsWorldConfig.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user