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); }
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()); }