using System; using System.Collections.Generic; using System.Reflection; namespace Encompass { internal class UberEngine : Engine { private readonly IEnumerable _componentTypes; private readonly IEnumerable _messageTypes; public Entity Entity { get; private set; } public UberEngine(IEnumerable componentTypes, IEnumerable messageTypes) { _componentTypes = componentTypes; _messageTypes = messageTypes; AddTypes.UnionWith(componentTypes); ReadTypes.UnionWith(componentTypes); WriteTypes.UnionWith(componentTypes); SendTypes.UnionWith(messageTypes); ReceiveTypes.UnionWith(messageTypes); } public void Write() { Entity = CreateEntity(); foreach (var type in _componentTypes) { var instance = Activator.CreateInstance(type); var instanceParam = new object[] { Entity, instance }; 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) { CallGenericWrappedMethod(type, "CallAllComponentMethods", null); } foreach (var type in _messageTypes) { CallGenericWrappedMethod(type, "CallAllMessageMethods", null); if (typeof(IHasEntity).IsAssignableFrom(type)) { CallGenericWrappedMethod(type, "CallAllEntityMessageMethods", null); } } } // we can't reflect invoke on byref returns or Span returns right now... so we have non-return wrapper methods protected void CallAllComponentMethods() where TComponent : struct { ReadComponent(); ReadComponents(); ReadEntity(); ReadEntities(); GetComponent(Entity); HasComponent(Entity); SomeComponent(); DestroyWith(); DestroyAllWith(); RemoveComponent(Entity); AddComponent(Entity, default); } protected void CallAllMessageMethods() where TMessage : struct { SendMessageIgnoringTimeDilation(default, 0.1); SendMessage(default); SendMessage(default, 0.1); ReadMessage(); ReadMessages(); SomeMessage(); } protected void CallAllEntityMessageMethods() where TMessage : struct, IHasEntity { ReadMessagesWithEntity(Entity); ReadMessageWithEntity(Entity); SomeMessageWithEntity(Entity); } 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); } } }