Updtae runners

This commit is contained in:
Mikhail 2023-03-12 02:02:39 +08:00
parent 6ae6775e00
commit 25fc3318d0
11 changed files with 179 additions and 169 deletions

View File

@ -1,10 +1,9 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class DestroyProcessor : IDo<_Run> public class DestroyProcessor : IEcsRunSystem
{ {
void IDo<_Run>.Do(EcsSession session) public void Run(EcsSession session)
{ {
} }
} }

View File

@ -6,13 +6,23 @@ using System.Threading.Tasks;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public interface IEcsInject<T> public interface IEcsInject<T> : IEcsProcessor
{ {
public void Inject(T obj); public void Inject(T obj);
} }
public class InjectProcessor<T> : IDo<_PreInit> public class InjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
{ {
void IEcsInject<T>.Inject(T obj)
{
foreach (var item in targets)
{
item.Inject(obj);
}
}
}
public class InjectProcessor<T> : IEcsPreInitSystem
{
private T _injectedData; private T _injectedData;
public InjectProcessor(T injectedData) public InjectProcessor(T injectedData)
@ -20,11 +30,10 @@ namespace DCFApixels.DragonECS
_injectedData = injectedData; _injectedData = injectedData;
} }
void IDo<_PreInit>.Do(EcsSession session) public void PreInit(EcsSession session)
{ {
var messenger = session.GetMessenger<_OnInject<T>>(); var injector = session.GetRunner<IEcsInject<T>>();
messenger.Send(new _OnInject<T>(_injectedData)); injector.Inject(_injectedData);
messenger.Destroy();
} }
} }

54
src/Builtin/Runners.cs Normal file
View File

@ -0,0 +1,54 @@
namespace DCFApixels.DragonECS
{
public interface IEcsPreInitSystem : IEcsProcessor
{
public void PreInit(EcsSession session);
}
public interface IEcsInitSystem : IEcsProcessor
{
public void Init(EcsSession session);
}
public interface IEcsRunSystem : IEcsProcessor
{
public void Run(EcsSession session);
}
public interface IEcsDestroySystem : IEcsProcessor
{
public void Destroy(EcsSession session);
}
public interface IEcsSimpleCycleSystem :
IEcsInitSystem,
IEcsRunSystem,
IEcsDestroySystem
{ }
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem
{
void IEcsPreInitSystem.PreInit(EcsSession session)
{
foreach (var item in targets) item.PreInit(session);
}
}
public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem
{
void IEcsInitSystem.Init(EcsSession session)
{
foreach (var item in targets) item.Init(session);
}
}
public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem
{
void IEcsRunSystem.Run(EcsSession session)
{
foreach (var item in targets) item.Run(session);
}
}
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem
{
void IEcsDestroySystem.Destroy(EcsSession session)
{
foreach (var item in targets) item.Destroy(session);
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 473f26450295507498d518fb452be90f guid: 074bd83936df7c84daf6e295b2f21a9a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -40,57 +40,34 @@ namespace DCFApixels.DragonECS
private int _id; private int _id;
private List<IEcsProcessor> _allProcessors; private List<IEcsProcessor> _allSystems;
private ReadOnlyCollection<IEcsProcessor> _allProcessorsSealed; private ReadOnlyCollection<IEcsProcessor> _allSystemsSealed;
private bool _isInit = false; private bool _isInit = false;
private bool _isDestoryed = false; private bool _isDestoryed = false;
private Dictionary<Type, IEcsProcessorsRunner> _runners; private Dictionary<Type, IEcsRunner> _runners;
private Dictionary<Type, IEcsProcessorsMessenger> _messengers; private IEcsRunSystem _runRunnerCache;
private EcsProcessorsRunner<_Run> _runRunnerCache;
private EcsWorldMap _worldMap = new EcsWorldMap(); private EcsWorldMap _worldMap = new EcsWorldMap();
#region Properties #region Properties
public ReadOnlyCollection<IEcsProcessor> AllProcessors => _allProcessorsSealed; public ReadOnlyCollection<IEcsProcessor> AllProcessors => _allSystemsSealed;
#endregion #endregion
#region React Runners/Messengers #region React Runners/Messengers
public EcsProcessorsRunner<TDoTag> GetRunner<TDoTag>() public T GetRunner<T>() where T : IEcsProcessor
{ {
Type type = typeof(TDoTag); Type type = typeof(T);
if (_runners.TryGetValue(type, out IEcsProcessorsRunner result)) if (_runners.TryGetValue(type, out IEcsRunner result))
{ {
return (EcsProcessorsRunner<TDoTag>)result; return (T)result;
} }
result = new EcsProcessorsRunner<TDoTag>(this); result = (IEcsRunner)EcsRunner<T>.Instantiate(_allSystems);
_runners.Add(type, result); _runners.Add(type, result);
return (EcsProcessorsRunner<TDoTag>)result; return (T)result;
}
internal void OnRunnerDetroyed<TDoTag>(EcsProcessorsRunner<TDoTag> target)
{
_runners.Remove(typeof(TDoTag));
}
public EcsProcessorsMessenger<TMessege> GetMessenger<TMessege>()
where TMessege : IEcsMessage
{
Type type = typeof(EcsProcessorsMessenger<TMessege>);
if (_messengers.TryGetValue(type, out IEcsProcessorsMessenger result))
{
return (EcsProcessorsMessenger<TMessege>)result;
}
result = new EcsProcessorsMessenger<TMessege>(this);
_messengers.Add(type, result);
return (EcsProcessorsMessenger<TMessege>)result;
}
internal void OnMessengerDetroyed<TMessege>(IEcsProcessorsMessenger<TMessege> target)
where TMessege : IEcsMessage
{
_messengers.Remove(typeof(TMessege));
} }
#endregion #endregion
@ -98,7 +75,7 @@ namespace DCFApixels.DragonECS
public EcsSession Add(IEcsProcessor system) public EcsSession Add(IEcsProcessor system)
{ {
CheckInitForMethod(nameof(AddWorld)); CheckInitForMethod(nameof(AddWorld));
_allProcessors.Add(system); _allSystems.Add(system);
return this; return this;
} }
public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "") public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "")
@ -116,29 +93,28 @@ namespace DCFApixels.DragonECS
{ {
CheckInitForMethod(nameof(Init)); CheckInitForMethod(nameof(Init));
_worldMap.Build(); _worldMap.Build();
_allProcessorsSealed = _allProcessors.AsReadOnly(); _allSystemsSealed = _allSystems.AsReadOnly();
_isInit = true; _isInit = true;
GetMessenger<_OnInject<EcsWorldMap>>().Send(new _OnInject<EcsWorldMap>(_worldMap)); GetRunner<IEcsInject<EcsWorldMap>>().Inject(_worldMap);
GetRunner<_PreInit>().Run(); GetRunner<IEcsPreInitSystem>().PreInit(this);
GetRunner<_Init>().Run(); GetRunner<IEcsInitSystem>().Init(this);
_runRunnerCache = GetRunner<_Run>(); _runRunnerCache = GetRunner<IEcsRunSystem>();
} }
public void Run() public void Run()
{ {
CheckDestroyForMethod(nameof(Run)); CheckDestroyForMethod(nameof(Run));
_runRunnerCache.Run(this);
_runRunnerCache.Run();
} }
public void Destroy() public void Destroy()
{ {
CheckDestroyForMethod(nameof(Run)); CheckDestroyForMethod(nameof(Run));
_isDestoryed = true; _isDestoryed = true;
GetRunner<_Destroy>().Run();
GetRunner<_PostDestroy>().Run(); GetRunner<IEcsDestroySystem>().Destroy(this);
} }
#endregion #endregion

View File

@ -1,53 +0,0 @@
namespace DCFApixels.DragonECS
{
public struct _PreInit { }
public struct _Init { }
public struct _Run { }
public struct _Destroy { }
public struct _PostDestroy { }
public interface IDo<TTag> : IEcsProcessor
{
public void Do(EcsSession session);
}
public interface IEcsSimpleCycleProcessor :
IDo<_Init>,
IDo<_Run>,
IDo<_Destroy>
{ }
public interface IEcsMessage { }
public readonly struct _OnNewEntityCreated : IEcsMessage
{
public readonly ent entity;
public _OnNewEntityCreated(ent entity)
{
this.entity = entity;
}
}
public readonly struct _OnNewEntityGenRecycled : IEcsMessage
{
public readonly ent entity;
public _OnNewEntityGenRecycled(ent entity)
{
this.entity = entity;
}
}
public readonly struct _OnInject<T> : IEcsMessage
{
public readonly T data;
public _OnInject(T data)
{
this.data = data;
}
}
public interface IReceive<TMessage> : IEcsProcessor
where TMessage : IEcsMessage
{
public void Do(EcsSession session, in TMessage m);
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c440e40c9802ce54fb7a84fda930b22d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5fb1c6ecbb7c4fd4692f54a92b7d198e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c8311d8200e99504693251ecdb1877c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -28,24 +28,80 @@ namespace DCFApixels.DragonECS
} }
} }
internal static class EcsRunnerActivator internal static class EcsRunnerActivator
{ {
private static bool _isInit = false; private static Dictionary<Guid, Type> _runnerTypes; //interface guid/ Runner type pairs;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Init() static EcsRunnerActivator()
{ {
if (_isInit) return; List<Exception> exceptions = new List<Exception>();
Type targetType = typeof(EcsRunner<>);
var subclasses = Assembly.GetAssembly(targetType).GetTypes().Where(type => type.BaseType != null && type.BaseType.IsGenericType && targetType == type.BaseType.GetGenericTypeDefinition()); Type runnerBaseType = typeof(EcsRunner<>);
foreach (var item in subclasses)
List<Type> newRunnerTypes = new List<Type>();
newRunnerTypes = Assembly.GetAssembly(runnerBaseType)
.GetTypes()
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition())
.ToList();
#if DEBUG
for (int i = 0; i < newRunnerTypes.Count; i++)
{ {
item.BaseType.GetMethod("Init", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { item }); var e = CheckRunnerValide(newRunnerTypes[i]);
if (e != null)
{
newRunnerTypes.RemoveAt(i--);
exceptions.Add(e);
}
} }
_isInit = true; #endif
_runnerTypes = new Dictionary<Guid, Type>();
foreach (var item in newRunnerTypes)
{
Type intrf = item.GetInterfaces()[2]; //TODO доработать это место. Во-первых убрать магическое число 2, во-вторых сделать так чтоб брался только наследованный интерфейс, а не все
_runnerTypes.Add(intrf.GUID, item);
}
if (exceptions.Count > 0)
{
foreach (var item in exceptions) throw item;
}
}
private static Exception CheckRunnerValide(Type type) //TODO доработать проверку валидности реалиазации ранера
{
if (type.ReflectedType != null)
return new Exception($"{type.FullName}.ReflectedType must be Null, but equal to {type.ReflectedType.FullName}");
//var interfaces = type.GetInterfaces();
//if (interfaces.Length != 1 || interfaces[0].GUID != typeof())
//{
//}
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InitFor<TInterface>() where TInterface : IEcsProcessor
{
Type interfaceType = typeof(TInterface);
Guid interfaceGuid = interfaceType.GUID;
if (!_runnerTypes.TryGetValue(interfaceGuid, out Type runnerType))
{
throw new Exception();
}
if (interfaceType.IsGenericType)
{
Type[] genericTypes = interfaceType.GetGenericArguments();
runnerType = runnerType.MakeGenericType(genericTypes);
}
EcsRunner<TInterface>.Init(runnerType);
} }
} }
public interface IEcsRunner { } public interface IEcsRunner { }
public abstract class EcsRunner<TInterface> : IEcsProcessor, IEcsRunner public abstract class EcsRunner<TInterface> : IEcsProcessor, IEcsRunner
@ -79,11 +135,11 @@ namespace DCFApixels.DragonECS
{ {
Type interfaceType = typeof(TInterface); Type interfaceType = typeof(TInterface);
IEnumerable<TInterface> newTargets = targets.OfType<TInterface>(); IEnumerable<IEcsProcessor> newTargets;
if (filter != null) if (filter != null)
{ {
newTargets = newTargets.Where(o => newTargets = targets.Where(o =>
{ {
if (o is TInterface == false) return false; if (o is TInterface == false) return false;
var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>(); var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>();
@ -92,7 +148,7 @@ namespace DCFApixels.DragonECS
} }
else else
{ {
newTargets = newTargets.Where(o => newTargets = targets.Where(o =>
{ {
if (o is TInterface == false) return false; if (o is TInterface == false) return false;
var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>(); var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>();
@ -100,20 +156,25 @@ namespace DCFApixels.DragonECS
}); });
} }
return Instantiate(newTargets.ToArray()); return Instantiate(newTargets.Select(o => (TInterface)o).ToArray());
} }
public static TInterface Instantiate(IEnumerable<IEcsProcessor> targets) public static TInterface Instantiate(IEnumerable<IEcsProcessor> targets)
{ {
return Instantiate(targets.OfType<TInterface>().ToArray()); return Instantiate(targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray());
} }
internal static TInterface Instantiate(TInterface[] targets) internal static TInterface Instantiate(TInterface[] targets)
{ {
EcsRunnerActivator.Init(); if (_subclass == null)
EcsRunnerActivator.InitFor<TInterface>();
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass); var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
return (TInterface)(IEcsProcessor)instance.Set(targets); return (TInterface)(IEcsProcessor)instance.Set(targets);
} }
private static Type _subclass; private static Type _subclass;
protected static void SetSublcass(Type type) => _subclass = type;
protected TInterface[] targets; protected TInterface[] targets;
private EcsRunner<TInterface> Set(TInterface[] targets) private EcsRunner<TInterface> Set(TInterface[] targets)

View File

@ -6,26 +6,23 @@ using System.Threading.Tasks;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class TestSystem : public class TestSystem :
IReceive<_OnInject<SharedData>>, IEcsInject<SharedData>,
IDo<_Init>, IDo<_Run>, IDo<_Destroy> IEcsSimpleCycleSystem
{ {
private SharedData _sharedData; private SharedData _sharedData;
void IReceive<_OnInject<SharedData>>.Do(EcsSession session, in _OnInject<SharedData> m) => _sharedData = m.data; public void Inject(SharedData obj) => _sharedData = obj;
void IDo<_Init>.Do(EcsSession session)
public void Init(EcsSession session)
{ {
} }
public void Run(EcsSession session)
void IDo<_Run>.Do(EcsSession session) {
{ }
public void Destroy(EcsSession session)
}
void IDo<_Destroy>.Do(EcsSession session)
{ {
} }
} }
} }