DragonECS/src/EcsWorld.static.cs

192 lines
7.0 KiB
C#
Raw Normal View History

2024-02-14 03:04:05 +08:00
using DCFApixels.DragonECS.Internal;
2023-06-25 23:22:01 +08:00
using System;
using System.Collections.Generic;
2024-11-01 12:41:10 +08:00
using System.ComponentModel;
2023-06-25 23:22:01 +08:00
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public partial class EcsWorld
2023-06-25 23:22:01 +08:00
{
2024-03-07 03:17:51 +08:00
private const short NULL_WORLD_ID = 0;
2024-11-15 15:08:44 +08:00
private const short GEN_STATUS_SEPARATOR = 0;
private const short GEN_WAKEUP_MASK = 0x7fff;
private const short GEN_SLEEP_MASK = ~GEN_WAKEUP_MASK;
2024-04-16 12:46:09 +08:00
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5;
private const int DEL_ENT_BUFFER_MIN_SIZE = 64;
2023-06-25 23:22:01 +08:00
2024-02-15 20:28:38 +08:00
private static EcsWorld[] _worlds = Array.Empty<EcsWorld>();
private static IdDispenser _worldIdDispenser = new IdDispenser(4, 0, n => Array.Resize(ref _worlds, n));
2023-06-25 23:22:01 +08:00
private static List<DataReleaser> _dataReleaseres = new List<DataReleaser>();
2024-01-29 01:09:17 +08:00
//public static int Copacity => Worlds.Length;
2023-06-25 23:22:01 +08:00
2024-09-09 18:21:21 +08:00
private static readonly object _worldLock = new object();
2023-06-25 23:22:01 +08:00
static EcsWorld()
{
2024-03-07 03:17:51 +08:00
_worlds[NULL_WORLD_ID] = new NullWorld();
2023-06-25 23:22:01 +08:00
}
private static void ReleaseData(int worldID)
{// ts
2024-09-09 18:21:21 +08:00
lock (_worldLock)
2024-02-15 00:53:20 +08:00
{
for (int i = 0, iMax = _dataReleaseres.Count; i < iMax; i++)
{
_dataReleaseres[i].Release(worldID);
}
2024-02-15 00:53:20 +08:00
}
2023-06-25 23:22:01 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-04-16 12:46:09 +08:00
public static EcsWorld GetWorld(short worldID)
{// ts
2024-04-16 12:46:09 +08:00
return _worlds[worldID];
}
2023-06-25 23:22:01 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-04-16 12:46:09 +08:00
public static ref T GetData<T>(int worldID)
{
return ref WorldComponentPool<T>.GetForWorld(worldID);
}
2023-07-03 02:44:35 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-04-16 12:46:09 +08:00
public static ref T GetDataUnchecked<T>(int worldID)
{
return ref WorldComponentPool<T>.GetForWorldUnchecked(worldID);
}
2023-06-25 23:22:01 +08:00
2023-06-25 23:22:01 +08:00
private abstract class DataReleaser
{
public abstract void Release(int worldID);
}
private static class WorldComponentPool<T>
{
private static T[] _items = new T[4];
private static short[] _mapping = new short[4];
private static short _count;
private static short[] _recycledItems = new short[4];
private static short _recycledItemsCount;
2023-06-25 23:22:01 +08:00
private static IEcsWorldComponent<T> _interface = EcsWorldComponentHandler<T>.instance;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-09-09 18:21:21 +08:00
public static ref T GetItem(int itemIndex)
{// ts
return ref _items[itemIndex];
}
2023-06-25 23:22:01 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetForWorld(int worldID)
{// зависит от GetItemIndex
2024-09-09 18:21:21 +08:00
return ref GetItem(GetItemIndex(worldID));
}
2023-07-02 16:17:13 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetForWorldUnchecked(int worldID)
{// ts
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-06 19:55:33 +08:00
if (_mapping[worldID] <= 0) { Throw.ArgumentOutOfRange(); }
#endif
return ref _items[_mapping[worldID]];
}
2023-06-25 23:22:01 +08:00
public static int GetItemIndex(int worldID)
{// ts
2024-02-15 20:28:38 +08:00
if (_mapping.Length < _worlds.Length)
2023-12-31 21:02:53 +08:00
{
2024-09-09 18:21:21 +08:00
lock (_worldLock)
2023-06-25 23:22:01 +08:00
{
if (_mapping.Length < _worlds.Length)
{
Array.Resize(ref _mapping, _worlds.Length);
}
2023-06-25 23:22:01 +08:00
}
}
short itemIndex = _mapping[worldID];
if (itemIndex == 0)
{
2024-09-09 18:21:21 +08:00
lock (_worldLock)
2023-12-31 21:02:53 +08:00
{
itemIndex = _mapping[worldID];
if (itemIndex <= 0)
{
if (_recycledItemsCount > 0)
{
_count++;
itemIndex = _recycledItems[--_recycledItemsCount];
}
else
{
itemIndex = ++_count;
}
_mapping[worldID] = itemIndex;
if (_items.Length <= itemIndex)
{
Array.Resize(ref _items, _items.Length << 1);
}
2024-09-09 18:21:21 +08:00
_interface.Init(ref _items[itemIndex], _worlds[worldID]);
_dataReleaseres.Add(new Releaser());
}
2023-12-31 21:02:53 +08:00
}
2023-06-25 23:22:01 +08:00
}
return itemIndex;
}
private static void Release(int worldID)
{// ts
2024-09-09 18:21:21 +08:00
lock (_worldLock)
2023-06-25 23:22:01 +08:00
{
if (_mapping.Length < _worlds.Length)
{
Array.Resize(ref _mapping, _worlds.Length);
}
ref short itemIndex = ref _mapping[worldID];
if (itemIndex != 0)
{
_interface.OnDestroy(ref _items[itemIndex], _worlds[worldID]);
2024-09-11 10:37:18 +08:00
if (_recycledItemsCount >= _recycledItems.Length)
2024-09-10 09:29:08 +08:00
{
Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
}
_recycledItems[_recycledItemsCount++] = itemIndex;
itemIndex = 0;
}
2023-06-25 23:22:01 +08:00
}
}
private sealed class Releaser : DataReleaser
{
public sealed override void Release(int worldID)
{
WorldComponentPool<T>.Release(worldID);
}
}
}
2024-02-03 01:12:53 +08:00
private sealed class NullWorld : EcsWorld
{
2024-03-10 21:47:28 +08:00
internal NullWorld() : base(new EcsWorldConfig(4, 4, 4, 4, 4), 0) { }
2024-02-03 01:12:53 +08:00
}
2024-11-01 12:41:10 +08:00
#region Obsolete
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use EcsWorld.ID")]
public short id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return ID; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The GetPoolInstance(int componentTypeID) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(int componentTypeID)
{
return FindPoolInstance(componentTypeID);
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The GetPoolInstance(Type componentType) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(Type componentType)
{
return FindPoolInstance(componentType);
}
#endregion
}
2023-06-25 23:22:01 +08:00
}