示例#1
0
        public void RegisterMod(ModHost modHost)
        {
            if (ModIdExists(modHost.ModID))
            {
                throw new DuplicateModIdException(modHost.ModID, "Mod with this ID has already been registered.");
            }

            Mods.Add(modHost);
        }
示例#2
0
        private void LoadMod(LoadData data)
        {
            var rootPath = data.RootDirectory;
            var manifest = data.Manifest;

            var targetModulePath = Path.Combine(rootPath, manifest.ModuleFileName);

            Log.Info($"Now trying to load '{targetModulePath}'");

            if (!File.Exists(targetModulePath))
            {
                Log.Error($"That was quick... Target DLL file does not exist.");
                return;
            }

            if (manifest.RequiredGSLs != null && manifest.RequiredGSLs.Length > 0)
            {
                foreach (var id in manifest.RequiredGSLs)
                {
                    if (!GameSupportLoader.IsGameSupportLibraryPresent(id))
                    {
                        Log.Error($"The mod requires a GSL with ID that is not present: {id}");
                        Log.Error("This mod will not be loaded. You need to install that GSL before loading that mod.");

                        return;
                    }
                }
            }

            if (manifest.Dependencies != null && manifest.Dependencies.Length > 0)
            {
                if (!LoadDependenciesForMod(rootPath, manifest.Dependencies))
                {
                    Log.Error("Failed to load dependencies.");
                    return;
                }
            }

            Assembly modAssembly;

            try
            {
                modAssembly = Assembly.LoadFrom(targetModulePath);
            }
            catch (ReflectionTypeLoadException rtle)
            {
                Log.ReflectionTypeLoadException(rtle);
                return;
            }
            catch (Exception e)
            {
                Log.Exception(e);
                return;
            }

            EnsureSingleEntryPoint(modAssembly);

            Type[] types;
            try
            {
                types = modAssembly.GetTypes();
            }
            catch (ReflectionTypeLoadException rtle)
            {
                Log.ReflectionTypeLoadException(rtle);
                return;
            }

            var entryPointType = FindEntryPointType(types);
            var entryPointInfo = GetEntryPointAttribute(entryPointType);

            EnsureModIdValid(entryPointInfo.ModID);

            var initMethodInfo = entryPointType.GetMethod(entryPointInfo.InitializerName, new Type[] { typeof(IManager) });

            if (initMethodInfo == null)
            {
                Log.Error($"Initializer method '{entryPointInfo.InitializerName}' accepting parameter of type 'IManager' not found.");
                return;
            }

            var messageHandlers = FindMessageHandlers(types);

            foreach (var messageHandler in messageHandlers)
            {
                Messenger.RegisterHandlerFor(messageHandler.ModID, messageHandler.MessageName, messageHandler.Method);
                Log.Info($"Registered message handler <{messageHandler.Method.Name}> for '{messageHandler.ModID}:{messageHandler.MessageName}'");
            }

            var modHost = new ModHost
            {
                Assembly   = modAssembly,
                ModID      = entryPointInfo.ModID,
                LoadData   = data,
                Instance   = null,
                GameObject = null
            };

            var dealingWithGameObject = MonoBehaviourBridge.MonoBehaviourType.IsAssignableFrom(entryPointType);

            if (dealingWithGameObject)
            {
                modHost.GameObject = GameObjectBridge.CreateGameObject(entryPointInfo.ModID);
                GameObjectBridge.DontDestroyOnLoad(modHost.GameObject);

                if (entryPointInfo.AwakeAfterInitialize)
                {
                    GameObjectBridge.SetActive(modHost.GameObject, false);
                }

                modHost.Instance = GameObjectBridge.AttachComponentTo(modHost.GameObject, entryPointType);
            }
            else
            {
                var instance = Activator.CreateInstance(entryPointType);
                modHost.Instance = instance;
            }

            var initializer = entryPointType.GetMethod(
                entryPointInfo.InitializerName,
                new Type[] { typeof(IManager) }
                );

            modHost.AssetLoaderMethod = entryPointType.GetMethod(
                entryPointInfo.LoaderMethodName,
                new Type[] { }
                );

            if (initializer != null)
            {
                Log.Info($"Now calling initializer method '{initializer.Name}' in '{modHost.Assembly.GetName().Name}'");

                try
                {
                    var args = new object[] { Manager };

                    if (initializer.IsStatic)
                    {
                        initializer.Invoke(null, args);
                    }
                    else
                    {
                        initializer.Invoke(modHost.Instance, args);
                    }
                }
                catch (Exception e)
                {
                    Log.Error("The initializer method has exploded spectacularly. Centrifuge and other mods will still work, though.");
                    Log.Exception(e);

                    if (dealingWithGameObject)
                    {
                        GameObjectBridge.Destroy(modHost.GameObject);
                    }

                    return;
                }
            }
            else
            {
                Log.Warning($"Did not find the initializer method '{entryPointInfo.InitializerName}' for Mod ID '{modHost.ModID}'. Seems like it doesn't exist. Loaded the mod anyway.");
            }

            if (dealingWithGameObject && entryPointInfo.AwakeAfterInitialize)
            {
                GameObjectBridge.SetActive(modHost.GameObject, true);
            }

            Registry.RegisterMod(modHost);
            Log.Info("Mod has been initialized and registered sucessfully.");

            Manager.OnModInitialized(modHost.ToExchangeableApiObject());
        }