using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using Sandbox; using Sandbox.Game.Entities; using Torch.Utils; using VRage.Game.Common; using VRage.Game.Components; using VRage.Game.Entity; using VRage.ObjectBuilders; using VRage.Plugins; using VRage.Utils; namespace Torch.Patches { /// /// There are places in static ctors where the registered assembly depends on the /// or . Here we force those registrations with the proper assemblies to ensure they work correctly. /// internal static class ObjectFactoryInitPatch { #pragma warning disable 649 [ReflectedGetter(Name = "m_objectFactory", TypeName = "Sandbox.Game.Entities.MyEntityFactory, Sandbox.Game")] private static Func> EntityFactoryObjectFactory; #pragma warning restore 649 internal static void ForceRegisterAssemblies() { var userAssemblies = MyPlugins.UserAssemblies; // static MyEntities() called by MySandboxGame.ForceStaticCtor RuntimeHelpers.RunClassConstructor(typeof(MyEntities).TypeHandle); { MyObjectFactory factory = EntityFactoryObjectFactory(); ObjectFactory_RegisterFromAssemblySafe(factory, typeof(MySandboxGame).Assembly); // calling assembly ObjectFactory_RegisterFromAssemblySafe(factory, MyPlugins.GameAssembly); ObjectFactory_RegisterFromAssemblySafe(factory, MyPlugins.SandboxAssembly); //ObjectFactory_RegisterFromAssemblySafe(factory, MyPlugins.UserAssembly); if (userAssemblies != null) { foreach (var assembly in userAssemblies) { ObjectFactory_RegisterFromAssemblySafe(factory, assembly); } } } // static MyGuiManager(): // MyGuiControlsFactory.RegisterDescriptorsFromAssembly(); // static MyComponentTypeFactory() called by MyComponentContainer.Add RuntimeHelpers.RunClassConstructor(typeof(MyComponentTypeFactory).TypeHandle); { ComponentTypeFactory_RegisterFromAssemblySafe(typeof(MyComponentContainer).Assembly); // calling assembly ComponentTypeFactory_RegisterFromAssemblySafe(MyPlugins.SandboxAssembly); ComponentTypeFactory_RegisterFromAssemblySafe(MyPlugins.GameAssembly); ComponentTypeFactory_RegisterFromAssemblySafe(MyPlugins.SandboxGameAssembly); //ComponentTypeFactory_RegisterFromAssemblySafe(MyPlugins.UserAssembly); if (userAssemblies != null) { foreach (var assembly in userAssemblies) { ComponentTypeFactory_RegisterFromAssemblySafe(assembly); } } } // static MyObjectPoolManager() // Render, so should be fine. } #region MyObjectFactory Adders private static void ObjectFactory_RegisterDescriptorSafe( MyObjectFactory factory, TAttribute descriptor, Type type) where TAttribute : MyFactoryTagAttribute where TCreatedObjectBase : class { if (factory.Attributes.TryGetValue(type, out _)) return; if (descriptor.ObjectBuilderType != null && factory.TryGetProducedType(descriptor.ObjectBuilderType) != null) return; if (typeof(MyObjectBuilder_Base).IsAssignableFrom(descriptor.ProducedType) && factory.TryGetProducedType(descriptor.ProducedType) != null) return; factory.RegisterDescriptor(descriptor, type); } private static void ObjectFactory_RegisterFromAssemblySafe(MyObjectFactory factory, Assembly assembly) where TAttribute : MyFactoryTagAttribute where TCreatedObjectBase : class { if (assembly == null) { return; } foreach (Type type in assembly.GetTypes()) { foreach (TAttribute descriptor in type.GetCustomAttributes()) { ObjectFactory_RegisterDescriptorSafe(factory, descriptor, type); } } } #endregion #region MyComponentTypeFactory Adders [ReflectedGetter(Name = "m_idToType", Type = typeof(MyComponentTypeFactory))] private static Func> ComponentTypeFactoryIdToType = null!; [ReflectedGetter(Name = "m_typeToId", Type = typeof(MyComponentTypeFactory))] private static Func> ComponentTypeFactoryTypeToId = null!; [ReflectedGetter(Name = "m_typeToContainerComponentType", Type = typeof(MyComponentTypeFactory))] private static Func> ComponentTypeFactoryContainerComponentType = null!; private static void ComponentTypeFactory_RegisterFromAssemblySafe(Assembly assembly) { if (assembly == null) return; foreach (Type type in assembly.GetTypes()) if (typeof(MyComponentBase).IsAssignableFrom(type)) { ComponentTypeFactory_AddIdSafe(type, MyStringId.GetOrCompute(type.Name)); ComponentTypeFactory_RegisterComponentTypeAttributeSafe(type); } } private static void ComponentTypeFactory_RegisterComponentTypeAttributeSafe(Type type) { Type componentType = type.GetCustomAttribute(true)?.ComponentType; if (componentType != null) ComponentTypeFactoryContainerComponentType()[type] = componentType; } private static void ComponentTypeFactory_AddIdSafe(Type type, MyStringId id) { ComponentTypeFactoryIdToType()[id] = type; ComponentTypeFactoryTypeToId()[type] = id; } #endregion } }