122 lines
5.6 KiB
C#
122 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Encompass
|
|
{
|
|
internal class UberEngine : Engine
|
|
{
|
|
private readonly IEnumerable<Type> _componentTypes;
|
|
private readonly IEnumerable<Type> _messageTypes;
|
|
public Entity Entity { get; private set; }
|
|
|
|
public UberEngine(IEnumerable<Type> componentTypes, IEnumerable<Type> messageTypes)
|
|
{
|
|
_componentTypes = componentTypes;
|
|
_messageTypes = messageTypes;
|
|
ReadTypes.UnionWith(componentTypes);
|
|
WriteTypes.UnionWith(componentTypes);
|
|
SendTypes.UnionWith(messageTypes);
|
|
ReceiveTypes.UnionWith(messageTypes);
|
|
}
|
|
|
|
public void Write()
|
|
{
|
|
Entity = CreateEntity();
|
|
|
|
foreach (var type in _componentTypes)
|
|
{
|
|
var instanceParam = new object[] { Entity, Activator.CreateInstance(type) };
|
|
var setComponentMethod = typeof(Engine).GetMethod("SetComponent", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
var genericSetComponentMethod = setComponentMethod.MakeGenericMethod(type);
|
|
genericSetComponentMethod.Invoke(this, instanceParam);
|
|
}
|
|
}
|
|
|
|
public override void Update(double dt)
|
|
{
|
|
foreach (var type in _componentTypes)
|
|
{
|
|
CallGenericMethod(type, "ReadComponent", null);
|
|
CallGenericWrappedMethod(type, "ReadComponentsWrapper", null);
|
|
CallGenericMethod(type, "ReadEntity", null);
|
|
CallGenericWrappedMethod(type, "ReadEntitiesWrapper", null);
|
|
CallGenericMethod(type, "GetComponent", new object[] { Entity });
|
|
CallGenericMethod(type, "HasComponent", 1, new object[] { Entity });
|
|
CallGenericMethod(type, "SomeComponent", null);
|
|
CallGenericMethod(type, "DestroyWith", null);
|
|
CallGenericMethod(type, "DestroyAllWith", null);
|
|
CallGenericMethod(type, "RemoveComponent", new object[] { Entity });
|
|
}
|
|
|
|
foreach (var type in _messageTypes)
|
|
{
|
|
CallGenericMethod(type, "SendMessageIgnoringTimeDilation", new object[] { Activator.CreateInstance(type), 1 });
|
|
CallGenericMethod(type, "SendMessage", 1, new object[] { Activator.CreateInstance(type) });
|
|
CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 });
|
|
CallGenericMethod(type, "ReadMessage", null);
|
|
|
|
CallGenericWrappedMethod(type, "ReadMessagesWrapper", null);
|
|
CallGenericMethod(type, "SomeMessage", null);
|
|
if (typeof(IHasEntity).IsAssignableFrom(type))
|
|
{
|
|
CallGenericMethod(type, "ReadMessagesWithEntity", new object[] { Entity });
|
|
CallGenericMethod(type, "ReadMessageWithEntity", new object[] { Entity });
|
|
CallGenericMethod(type, "SomeMessageWithEntity", new object[] { Entity });
|
|
}
|
|
}
|
|
}
|
|
|
|
// we can't reflect invoke on Span returns right now... so we have non-return wrapper methods
|
|
|
|
protected void ReadComponentsWrapper<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
ReadComponents<TComponent>();
|
|
}
|
|
|
|
protected void ReadMessagesWrapper<TMessage>() where TMessage : struct, IMessage
|
|
{
|
|
ReadMessages<TMessage>();
|
|
}
|
|
|
|
protected void ReadEntitiesWrapper<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
ReadEntities<TComponent>();
|
|
}
|
|
|
|
// trying to use PrepareMethod because we can't reflect invoke methods that return a span...
|
|
private void CallGenericMethod(Type type, string methodName, object[] parameters)
|
|
{
|
|
var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
|
|
var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type);
|
|
genericReadComponentMethod.Invoke(this, parameters);
|
|
// RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle);
|
|
}
|
|
|
|
private void CallGenericWrappedMethod(Type type, string methodName, object[] parameters)
|
|
{
|
|
var readComponentMethod = typeof(UberEngine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
|
|
var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type);
|
|
genericReadComponentMethod.Invoke(this, parameters);
|
|
}
|
|
|
|
private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters)
|
|
{
|
|
var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
|
|
var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type);
|
|
genericReadComponentMethod.Invoke(this, parameters);
|
|
// RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle);
|
|
}
|
|
|
|
private void CallGenericMethod(Type type, string methodName, int argumentNum, object[] parameters)
|
|
{
|
|
var method = typeof(Engine).GetRuntimeMethods().Where(m => m.Name == methodName && m.GetParameters().Length == argumentNum).First();
|
|
var genericMethod = method.MakeGenericMethod(type);
|
|
genericMethod.Invoke(this, parameters);
|
|
// RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle);
|
|
}
|
|
}
|
|
}
|