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
{
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
{
public interface IEcsInject<T>
public interface IEcsInject<T> : IEcsProcessor
{
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;
public InjectProcessor(T injectedData)
@ -20,11 +30,10 @@ namespace DCFApixels.DragonECS
_injectedData = injectedData;
}
void IDo<_PreInit>.Do(EcsSession session)
public void PreInit(EcsSession session)
{
var messenger = session.GetMessenger<_OnInject<T>>();
messenger.Send(new _OnInject<T>(_injectedData));
messenger.Destroy();
var injector = session.GetRunner<IEcsInject<T>>();
injector.Inject(_injectedData);
}
}

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
guid: 473f26450295507498d518fb452be90f
guid: 074bd83936df7c84daf6e295b2f21a9a
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -40,57 +40,34 @@ namespace DCFApixels.DragonECS
private int _id;
private List<IEcsProcessor> _allProcessors;
private ReadOnlyCollection<IEcsProcessor> _allProcessorsSealed;
private List<IEcsProcessor> _allSystems;
private ReadOnlyCollection<IEcsProcessor> _allSystemsSealed;
private bool _isInit = false;
private bool _isDestoryed = false;
private Dictionary<Type, IEcsProcessorsRunner> _runners;
private Dictionary<Type, IEcsProcessorsMessenger> _messengers;
private EcsProcessorsRunner<_Run> _runRunnerCache;
private Dictionary<Type, IEcsRunner> _runners;
private IEcsRunSystem _runRunnerCache;
private EcsWorldMap _worldMap = new EcsWorldMap();
#region Properties
public ReadOnlyCollection<IEcsProcessor> AllProcessors => _allProcessorsSealed;
public ReadOnlyCollection<IEcsProcessor> AllProcessors => _allSystemsSealed;
#endregion
#region React Runners/Messengers
public EcsProcessorsRunner<TDoTag> GetRunner<TDoTag>()
public T GetRunner<T>() where T : IEcsProcessor
{
Type type = typeof(TDoTag);
if (_runners.TryGetValue(type, out IEcsProcessorsRunner result))
Type type = typeof(T);
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);
return (EcsProcessorsRunner<TDoTag>)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));
return (T)result;
}
#endregion
@ -98,7 +75,7 @@ namespace DCFApixels.DragonECS
public EcsSession Add(IEcsProcessor system)
{
CheckInitForMethod(nameof(AddWorld));
_allProcessors.Add(system);
_allSystems.Add(system);
return this;
}
public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "")
@ -116,29 +93,28 @@ namespace DCFApixels.DragonECS
{
CheckInitForMethod(nameof(Init));
_worldMap.Build();
_allProcessorsSealed = _allProcessors.AsReadOnly();
_allSystemsSealed = _allSystems.AsReadOnly();
_isInit = true;
GetMessenger<_OnInject<EcsWorldMap>>().Send(new _OnInject<EcsWorldMap>(_worldMap));
GetRunner<IEcsInject<EcsWorldMap>>().Inject(_worldMap);
GetRunner<_PreInit>().Run();
GetRunner<_Init>().Run();
GetRunner<IEcsPreInitSystem>().PreInit(this);
GetRunner<IEcsInitSystem>().Init(this);
_runRunnerCache = GetRunner<_Run>();
_runRunnerCache = GetRunner<IEcsRunSystem>();
}
public void Run()
{
CheckDestroyForMethod(nameof(Run));
_runRunnerCache.Run();
_runRunnerCache.Run(this);
}
public void Destroy()
{
CheckDestroyForMethod(nameof(Run));
_isDestoryed = true;
GetRunner<_Destroy>().Run();
GetRunner<_PostDestroy>().Run();
GetRunner<IEcsDestroySystem>().Destroy(this);
}
#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
{
private static bool _isInit = false;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Init()
private static Dictionary<Guid, Type> _runnerTypes; //interface guid/ Runner type pairs;
static EcsRunnerActivator()
{
if (_isInit) return;
Type targetType = typeof(EcsRunner<>);
var subclasses = Assembly.GetAssembly(targetType).GetTypes().Where(type => type.BaseType != null && type.BaseType.IsGenericType && targetType == type.BaseType.GetGenericTypeDefinition());
foreach (var item in subclasses)
List<Exception> exceptions = new List<Exception>();
Type runnerBaseType = typeof(EcsRunner<>);
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 abstract class EcsRunner<TInterface> : IEcsProcessor, IEcsRunner
@ -79,11 +135,11 @@ namespace DCFApixels.DragonECS
{
Type interfaceType = typeof(TInterface);
IEnumerable<TInterface> newTargets = targets.OfType<TInterface>();
IEnumerable<IEcsProcessor> newTargets;
if (filter != null)
{
newTargets = newTargets.Where(o =>
newTargets = targets.Where(o =>
{
if (o is TInterface == false) return false;
var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>();
@ -92,7 +148,7 @@ namespace DCFApixels.DragonECS
}
else
{
newTargets = newTargets.Where(o =>
newTargets = targets.Where(o =>
{
if (o is TInterface == false) return false;
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)
{
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)
{
EcsRunnerActivator.Init();
if (_subclass == null)
EcsRunnerActivator.InitFor<TInterface>();
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
return (TInterface)(IEcsProcessor)instance.Set(targets);
}
private static Type _subclass;
protected static void SetSublcass(Type type) => _subclass = type;
protected TInterface[] targets;
private EcsRunner<TInterface> Set(TInterface[] targets)

View File

@ -6,26 +6,23 @@ using System.Threading.Tasks;
namespace DCFApixels.DragonECS
{
public class TestSystem :
IReceive<_OnInject<SharedData>>,
IDo<_Init>, IDo<_Run>, IDo<_Destroy>
public class TestSystem :
IEcsInject<SharedData>,
IEcsSimpleCycleSystem
{
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)
{
}
void IDo<_Run>.Do(EcsSession session)
{
}
void IDo<_Destroy>.Do(EcsSession session)
public void Run(EcsSession session)
{
}
public void Destroy(EcsSession session)
{
}
}
}