encompass-cs/encompass-cs/UberEngine.cs

99 lines
4.7 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);
}
}
// we can't reflect invoke on Span returns right now... tragic
public override void Update(double dt)
{
foreach (var type in _componentTypes)
{
CallGenericMethod(type, "ReadComponent", null);
//CallGenericMethod(type, "ReadComponents", null);
CallGenericMethod(type, "ReadEntity", null);
//CallGenericMethod(type, "ReadEntities", 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);
//CallGenericMethod(type, "ReadMessages", 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 });
}
}
}
// 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 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);
}
}
}