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;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
|
|
|
|
{
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 4)]
|
|
|
|
|
public struct EcsWorldCmp<T> where T : struct
|
|
|
|
|
{
|
2024-04-16 12:46:09 +08:00
|
|
|
|
private short _worldID;
|
|
|
|
|
public EcsWorldCmp(short worldID) => _worldID = worldID;
|
2023-06-25 23:22:01 +08:00
|
|
|
|
public EcsWorld World => EcsWorld.GetWorld(_worldID);
|
|
|
|
|
public ref T Value => ref EcsWorld.GetData<T>(_worldID);
|
|
|
|
|
}
|
2024-02-22 15:39:37 +08:00
|
|
|
|
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-04-16 12:46:09 +08:00
|
|
|
|
private const short WAKE_UP_GEN_MASK = 0x7fff;
|
|
|
|
|
private const short SLEEP_GEN_MASK = ~WAKE_UP_GEN_MASK;
|
|
|
|
|
|
2024-02-29 22:42:33 +08:00
|
|
|
|
private const short SLEEPING_GEN_FLAG = short.MinValue;
|
2023-11-22 11:53:41 +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, OnWorldIdDispenser);
|
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
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0, iMax = _dataReleaseres.Count; i < iMax; i++)
|
2024-02-15 00:53:20 +08:00
|
|
|
|
{
|
2023-06-25 23:22:01 +08:00
|
|
|
|
_dataReleaseres[i].Release(worldID);
|
2024-02-15 00:53:20 +08:00
|
|
|
|
}
|
2023-06-25 23:22:01 +08:00
|
|
|
|
}
|
2024-02-15 20:28:38 +08:00
|
|
|
|
public static void OnWorldIdDispenser(int newSize)
|
|
|
|
|
{
|
|
|
|
|
Array.Resize(ref _worlds, newSize);
|
|
|
|
|
}
|
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)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
private abstract class DataReleaser
|
|
|
|
|
{
|
|
|
|
|
public abstract void Release(int worldID);
|
|
|
|
|
}
|
|
|
|
|
private static class WorldComponentPool<T>
|
|
|
|
|
{
|
|
|
|
|
private static T[] _items = new T[4];
|
2023-06-27 01:23:01 +08:00
|
|
|
|
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)]
|
2023-12-31 13:07:53 +08:00
|
|
|
|
public static ref T Get(int itemIndex)
|
|
|
|
|
{
|
|
|
|
|
return ref _items[itemIndex];
|
|
|
|
|
}
|
2023-06-25 23:22:01 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-12-31 13:07:53 +08:00
|
|
|
|
public static ref T GetForWorld(int worldID)
|
|
|
|
|
{
|
2023-12-31 21:02:53 +08:00
|
|
|
|
int index = GetItemIndex(worldID);
|
|
|
|
|
return ref _items[index];
|
2023-12-31 13:07:53 +08:00
|
|
|
|
}
|
2023-07-02 16:17:13 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-12-31 13:07:53 +08:00
|
|
|
|
public static ref T GetForWorldUnchecked(int worldID)
|
|
|
|
|
{
|
|
|
|
|
#if (DEBUG && !DISABLE_DEBUG)
|
2024-03-07 03:17:51 +08:00
|
|
|
|
if (_mapping[worldID] <= 0) { Throw.UndefinedException(); }
|
2023-12-31 13:07:53 +08:00
|
|
|
|
#endif
|
|
|
|
|
return ref _items[_mapping[worldID]];
|
|
|
|
|
}
|
2023-06-25 23:22:01 +08:00
|
|
|
|
public static int GetItemIndex(int worldID)
|
|
|
|
|
{
|
2024-02-15 20:28:38 +08:00
|
|
|
|
if (_mapping.Length < _worlds.Length)
|
2023-12-31 21:02:53 +08:00
|
|
|
|
{
|
2024-02-15 20:28:38 +08:00
|
|
|
|
Array.Resize(ref _mapping, _worlds.Length);
|
2023-12-31 21:02:53 +08:00
|
|
|
|
}
|
2023-06-27 01:23:01 +08:00
|
|
|
|
ref short itemIndex = ref _mapping[worldID];
|
2023-06-25 23:22:01 +08:00
|
|
|
|
if (itemIndex <= 0)
|
|
|
|
|
{
|
|
|
|
|
if (_recycledItemsCount > 0)
|
|
|
|
|
{
|
|
|
|
|
_count++;
|
|
|
|
|
itemIndex = _recycledItems[--_recycledItemsCount];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
itemIndex = ++_count;
|
|
|
|
|
}
|
2024-01-07 19:32:16 +08:00
|
|
|
|
if (_items.Length <= itemIndex)
|
2023-12-31 21:02:53 +08:00
|
|
|
|
{
|
|
|
|
|
Array.Resize(ref _items, _items.Length << 1);
|
|
|
|
|
}
|
2024-02-15 20:28:38 +08:00
|
|
|
|
_interface.Init(ref _items[itemIndex], _worlds[worldID]);
|
2023-06-25 23:22:01 +08:00
|
|
|
|
_dataReleaseres.Add(new Releaser());
|
|
|
|
|
}
|
|
|
|
|
return itemIndex;
|
|
|
|
|
}
|
|
|
|
|
private static void Release(int worldID)
|
|
|
|
|
{
|
2024-05-01 15:14:36 +08:00
|
|
|
|
if (_mapping.Length < _worlds.Length)
|
|
|
|
|
{
|
|
|
|
|
Array.Resize(ref _mapping, _worlds.Length);
|
|
|
|
|
}
|
2023-06-27 01:23:01 +08:00
|
|
|
|
ref short itemIndex = ref _mapping[worldID];
|
2023-06-25 23:22:01 +08:00
|
|
|
|
if (itemIndex != 0)
|
|
|
|
|
{
|
2024-02-15 20:28:38 +08:00
|
|
|
|
_interface.OnDestroy(ref _items[itemIndex], _worlds[worldID]);
|
2023-06-25 23:22:01 +08:00
|
|
|
|
_recycledItems[_recycledItemsCount++] = itemIndex;
|
2024-02-25 02:33:18 +08:00
|
|
|
|
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
|
|
|
|
}
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
2023-06-25 23:22:01 +08:00
|
|
|
|
}
|