using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Encompass { internal class UberEngine : Engine { private IEnumerable _componentTypes; private IEnumerable _messageTypes; private Entity _entity; public UberEngine(Entity entity, IEnumerable componentTypes, IEnumerable messageTypes) { _componentTypes = componentTypes; _messageTypes = messageTypes; readTypes.UnionWith(componentTypes); writeTypes.UnionWith(componentTypes); sendTypes.UnionWith(messageTypes); receiveTypes.UnionWith(messageTypes); _entity = entity; } public void Write() { 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); CallGenericMethod(type, "ReadComponentIncludingEntity", null); CallGenericMethod(type, "ReadComponents", null); CallGenericMethod(type, "ReadComponentsIncludingEntity", null); CallGenericMethod(type, "GetComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); CallGenericMethod(type, "HasComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); CallGenericMethod(type, "SomeComponent", null); CallGenericMethod(type, "RemoveComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); CallGenericMethod(type, "DestroyWith", null); CallGenericMethod(type, "DestroyAllWith", null); } 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); } } 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); } 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); } 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); } } }