/// <summary> /// Searches for script type assemblies in the specified path, and loads /// any script types that are found into a registry. /// </summary> /// <remarks> /// A script type is loaded if the class implements <see cref="IScriptType"/> and is /// not abstract. Once loaded, the type is added to the registry. /// </remarks> /// <param name="p_strSearchPath">The path in which to search for script type assemblies.</param> /// <param name="p_gmdGameMode">The current game mode.</param> /// <returns>A registry containing all of the discovered script types.</returns> public static IScriptTypeRegistry DiscoverScriptTypes(string p_strSearchPath, IGameMode p_gmdGameMode) { Trace.TraceInformation("Discovering Script Types..."); Trace.Indent(); Trace.TraceInformation("Discovering Generic Script Types..."); Trace.Indent(); Trace.TraceInformation("Looking in: {0}", p_strSearchPath); IScriptTypeRegistry stgRegistry = new ScriptTypeRegistry(); if (!Directory.Exists(p_strSearchPath)) { Trace.TraceError("Script Type search path does not exist."); Trace.Unindent(); Trace.Unindent(); return stgRegistry; } string[] strAssemblies = Directory.GetFiles(p_strSearchPath, "*.dll"); RegisterScriptTypes(stgRegistry, strAssemblies); Trace.Unindent(); Trace.TraceInformation("Discovering Game Mode Specific Script Types..."); Trace.Indent(); string strGameModeSearchPath = Path.GetDirectoryName(Assembly.GetAssembly(p_gmdGameMode.GetType()).Location); Trace.TraceInformation("Looking in: {0}", strGameModeSearchPath); if (!Directory.Exists(strGameModeSearchPath)) { Trace.TraceError("Game Mode Specific Script Type search path does not exist."); Trace.Unindent(); Trace.Unindent(); return stgRegistry; } List<string> lstAssemblies = new List<string>(); foreach (IScriptType stpType in stgRegistry.Types) lstAssemblies.AddRange(Directory.GetFiles(strGameModeSearchPath, String.Format("{0}.{1}.dll", p_gmdGameMode.ModeId, stpType.TypeId))); RegisterScriptTypes(stgRegistry, lstAssemblies); Trace.Unindent(); Trace.Unindent(); return stgRegistry; }
public static void SetInitSlot(this IGameMode actor) { var type = actor.GetType(); if (!type.IsAssignableTo(typeof(MonoBehaviour))) { return; } PrefabFactory defaultFactory = null; if (type.GetCustomAttribute(typeof(ReadFromFactoryClassAttribute)) is ReadFromFactoryClassAttribute attr) { defaultFactory = actor.PrefabFactoryManager.GetFactory(attr.FactoryName); } var fields = type.GetFields(ReflectionHelper.InstanceMemberFinder); foreach (var field in fields) { if (field.FieldType.IsAssignableTo(typeof(IActor)) || field.FieldType.IsAssignableTo(typeof(GameObject))) { var initSlot = field.GetCustomAttribute(typeof(ReadFromFactorySlotAttribute)) as ReadFromFactorySlotAttribute; if (initSlot is null) { continue; } var factory = !(initSlot.FactoryName is null) ? actor.PrefabFactoryManager.GetFactory(initSlot.FactoryName) : defaultFactory; if (factory is null) { throw new InitSlotException($"PrefabFactory of type {initSlot.FactoryName} doesn't exist."); } if (!(factory.GetType().GetField(initSlot.PropertyName, ReflectionHelper.InstanceMemberFinder)?.GetValue(factory) is GameObject prefab)) { throw new InitSlotException($"type {initSlot.FactoryName} doesn't have a field {initSlot.PropertyName} typed {nameof(PrefabFactory)}"); } var newObj = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.identity, actor.gameObject.transform); if (field.FieldType.IsAssignableTo(typeof(GameObject))) { ReflectionHelper.SetField(actor, field, newObj); } else if (field.FieldType.IsAssignableTo(typeof(IActor))) { ReflectionHelper.SetField(actor, field, newObj.GetComponent(field.FieldType)); } } } var properties = type.GetProperties(ReflectionHelper.InstanceMemberFinder); foreach (var property in properties) { if (property.PropertyType.IsAssignableTo(typeof(IActor)) || property.PropertyType.IsAssignableTo(typeof(GameObject))) { var initSlot = property.GetCustomAttribute(typeof(ReadFromFactorySlotAttribute)) as ReadFromFactorySlotAttribute; if (initSlot is null) { continue; } var factory = !(initSlot.FactoryName is null) ? actor.PrefabFactoryManager.GetFactory(initSlot.FactoryName) : defaultFactory; if (factory is null) { throw new InitSlotException($"PrefabFactory of type {initSlot.FactoryName} doesn't exist."); } if (!(factory.GetType().GetField(initSlot.PropertyName, ReflectionHelper.InstanceMemberFinder)?.GetValue(factory) is GameObject prefab)) { throw new InitSlotException($"type {initSlot.FactoryName} doesn't have a field {initSlot.PropertyName} typed {nameof(PrefabFactory)}"); } var newObj = UnityEngine.Object.Instantiate(prefab, Vector3.zero, Quaternion.identity, actor.gameObject.transform); if (property.PropertyType.IsAssignableTo(typeof(GameObject))) { ReflectionHelper.SetProperty(actor, property, newObj); } else if (property.PropertyType.IsAssignableTo(typeof(IActor))) { ReflectionHelper.SetProperty(actor, property, newObj.GetComponent(property.PropertyType)); } } } }
/// <summary> /// Searches for script type assemblies in the specified path, and loads /// any script types that are found into a registry. /// </summary> /// <remarks> /// A script type is loaded if the class implements <see cref="IScriptType"/> and is /// not abstract. Once loaded, the type is added to the registry. /// </remarks> /// <param name="p_strSearchPath">The path in which to search for script type assemblies.</param> /// <param name="p_gmdGameMode">The current game mode.</param> /// <returns>A registry containing all of the discovered script types.</returns> public static IScriptTypeRegistry DiscoverScriptTypes(string p_strSearchPath, IGameMode p_gmdGameMode) { Trace.TraceInformation("Discovering Script Types..."); Trace.Indent(); Trace.TraceInformation("Discovering Generic Script Types..."); Trace.Indent(); Trace.TraceInformation("Looking in: {0}", p_strSearchPath); IScriptTypeRegistry stgRegistry = new ScriptTypeRegistry(); if (!Directory.Exists(p_strSearchPath)) { Trace.TraceError("Script Type search path does not exist."); Trace.Unindent(); Trace.Unindent(); return(stgRegistry); } string[] strAssemblies = Directory.GetFiles(p_strSearchPath, "*.dll"); RegisterScriptTypes(stgRegistry, strAssemblies); Trace.Unindent(); Trace.TraceInformation("Discovering Game Mode Specific Script Types..."); Trace.Indent(); string strGameModeSearchPath = Path.GetDirectoryName(Assembly.GetAssembly(p_gmdGameMode.GetType()).Location); Trace.TraceInformation("Looking in: {0}", strGameModeSearchPath); if (!Directory.Exists(strGameModeSearchPath)) { Trace.TraceError("Game Mode Specific Script Type search path does not exist."); Trace.Unindent(); Trace.Unindent(); return(stgRegistry); } List <string> lstAssemblies = new List <string>(); foreach (IScriptType stpType in stgRegistry.Types) { lstAssemblies.AddRange(Directory.GetFiles(strGameModeSearchPath, String.Format("{0}.{1}.dll", p_gmdGameMode.ModeId, stpType.TypeId))); } RegisterScriptTypes(stgRegistry, lstAssemblies); Trace.Unindent(); Trace.Unindent(); return(stgRegistry); }
/// <summary> /// returns a list of the class names of all maps that support the given game mode /// </summary> /// <param name="gameMode"></param> /// <returns></returns> public static IEnumerable<string> GetSupportedMapsForGameMode(IGameMode gameMode) { return GetSupportedMapsForGameMode(gameMode.GetType().Name); }
static int DoInstall(string game, string filename, string installationPath, string profilePath, string gamePath, List <string> additionalSearchPaths, string seVersion, ref string errorString) { if (game == null) { errorString = "no game specified"; return(1); } if (filename == null) { errorString = "no file specified"; return(1); } if (profilePath == null) { errorString = "no profile path specified"; return(1); } if (gamePath == null) { errorString = "no game path specified"; return(1); } try { EnvironmentInfo environmentInfo = new EnvironmentInfo(Properties.Settings.Default); string exeLocation = Assembly.GetExecutingAssembly().Location; string exePath = System.IO.Path.GetDirectoryName(exeLocation); string[] gameModes = Directory.GetFiles(Path.Combine(exePath, "GameModes"), String.Format("{0}.dll", game)); if (gameModes.Count() == 0) { errorString = "unknown game"; return(1); } Assembly gameAssembly = Assembly.LoadFrom(gameModes[0]); IGameModeFactory gameModeFactory = null; Type[] exportedTypes = gameAssembly.GetExportedTypes(); foreach (Type type in exportedTypes) { if (typeof(IGameModeFactory).IsAssignableFrom(type) && !type.IsAbstract) { ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(EnvironmentInfo) }); gameModeFactory = (IGameModeFactory)constructor.Invoke(new Object[] { environmentInfo }); } } if (gameModeFactory == null) { errorString = "invalid game"; return(1); } string str7zPath = Path.Combine(environmentInfo.ProgrammeInfoDirectory, environmentInfo.Is64BitProcess ? "7z-64bit.dll" : "7z-32bit.dll"); SevenZipCompressor.SetLibraryPath(str7zPath); FileUtil fileUtil = new NexusFileUtil(environmentInfo); environmentInfo.Settings.InstallationPaths[gameModeFactory.GameModeDescriptor.ModeId] = installationPath; environmentInfo.Settings.ModFolder[gameModeFactory.GameModeDescriptor.ModeId] = installationPath; // environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = environmentInfo.TemporaryPath; environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = Path.Combine(installationPath, "temp"); if (environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] == null) { environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] = new KeyedSettings <string>(); } if (environmentInfo.Settings.DelayedSettings["ALL"] == null) { environmentInfo.Settings.DelayedSettings["ALL"] = new KeyedSettings <string>(); } ViewMessage warning = null; IGameMode gameMode = gameModeFactory.BuildGameMode(fileUtil, out warning); IModCacheManager cacheManager = new NexusModCacheManager(environmentInfo.TemporaryPath, gameMode.GameModeEnvironmentInfo.ModDirectory, fileUtil); IScriptTypeRegistry scriptTypeRegistry = ScriptTypeRegistry.DiscoverScriptTypes(Path.Combine(Path.GetDirectoryName(exeLocation), "ScriptTypes"), gameMode, new List <string>()); if (scriptTypeRegistry.Types.Count == 0) { errorString = "No script types were found."; return(2); } // use a proxy so we can intercept accesses to the IGameMode interface. This allows us to make the additional search paths accessible from // the sandbox and feed in the script extender version even though the nmm lib won't find it. // This has to happen after DiscoverScriptTypes becaus that function tries to localize the assembly which fails for the dynamic assembly // of the proxy. Fortunately DiscoverScriptTypes has no side-effects on the gameMode. // This recreates the gamemode object so it's important no code above modifies gameMode ProxyGenerator generator = new ProxyGenerator(); GameModeInterceptor interceptor = new GameModeInterceptor(additionalSearchPaths, seVersion != null ? new Version(seVersion) : null); gameMode = (IGameMode)generator.CreateClassProxy(gameMode.GetType(), new object[] { environmentInfo, fileUtil }, new IInterceptor[] { interceptor }); IModFormatRegistry formatRegistry = ModFormatRegistry.DiscoverFormats(cacheManager, gameMode.SupportedFormats, scriptTypeRegistry, Path.Combine(Path.GetDirectoryName(exeLocation), "ModFormats")); if (formatRegistry.Formats.Count == 0) { errorString = "No formats were found."; return(2); } // we install the mod from the temporary path. Unfortunately this requires the archive to be copied, otherwise the sandbox will // prevent the installer script from accessing the archive in its original location string fileNameTemporary = Path.Combine(environmentInfo.TemporaryPath, Path.GetFileName(filename)); File.Copy(filename, fileNameTemporary); IMod mod = CreateMod(fileNameTemporary, formatRegistry, gameMode); if (mod == null) { errorString = "failed to initialize mod"; return(3); } System.IO.File.WriteAllText(installationPath + "/__installInfo.txt", mod.ModName + "\n" + mod.HumanReadableVersion + "\n" + mod.Id); if (mod.HasInstallScript) { DummyDataFileUtilFactory dummyFactory = null; IDataFileUtil dataFileUtility; Logger.Info("Detected C# script that relies on files in the actual data folder"); string modlistFile = Path.Combine(profilePath, "modlist.txt"); // ASSUMED mods path is the parent directory of the gameMode.InstallationPath string modsPath = Directory.GetParent(gameMode.InstallationPath).FullName; // Prepare dummy data directory dummyFactory = new DummyDataFileUtilFactory(gameMode.GameModeEnvironmentInfo.InstallationPath, modlistFile, modsPath, gamePath, additionalSearchPaths); dataFileUtility = dummyFactory.CreateDummyDataFileUtil(); TxFileManager fileManager = new TxFileManager(); IInstallLog installLog = new DummyInstallLog(); IIniInstaller iniIniInstaller = new IniInstaller(mod, installLog, fileManager, delegate { return(OverwriteResult.No); }); IPluginManager pluginManager = new DummyPluginManager(Path.Combine(profilePath, "plugins.txt"), gameMode, mod); IGameSpecificValueInstaller gameSpecificValueInstaller = gameMode.GetGameSpecificValueInstaller(mod, installLog, fileManager, new NexusFileUtil(environmentInfo), delegate { return(OverwriteResult.No); }); IModFileInstaller fileInstaller = new ModFileInstaller(gameMode.GameModeEnvironmentInfo, mod, installLog, pluginManager, dataFileUtility, fileManager, delegate { return(OverwriteResult.No); }, false); InstallerGroup installers = new InstallerGroup(dataFileUtility, fileInstaller, iniIniInstaller, gameSpecificValueInstaller, pluginManager); IVirtualModActivator modActivator = new DummyVirtualModActivator(gameMode, environmentInfo); IScriptExecutor executor = mod.InstallScript.Type.CreateExecutor(mod, gameMode, environmentInfo, modActivator, installers, SynchronizationContext.Current); // run the script in a second thread and start the main loop in the main thread to ensure we can handle message boxes and the like ScriptRunner runner = new ScriptRunner(executor, mod.InstallScript); runner.Execute(); runner.TaskEnded += delegate { iniIniInstaller.FinalizeInstall(); gameSpecificValueInstaller.FinalizeInstall(); mod.EndReadOnlyTransaction(); Application.Exit(); }; Application.Run(); switch (runner.Status) { case BackgroundTasks.TaskStatus.Cancelled: return(11); case BackgroundTasks.TaskStatus.Error: return(6); case BackgroundTasks.TaskStatus.Incomplete: return(10); default: return(0); } } else { errorString = "no install script"; return(4); } } catch (Exception e) { Console.WriteLine("exception: " + e.Message); MessageBox.Show(e.Message, "Installation failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return(5); } }
/// <summary> /// returns a list of the class names of all maps that support the given game mode /// </summary> /// <param name="gameMode"></param> /// <returns></returns> public static IEnumerable <string> GetSupportedMapsForGameMode(IGameMode gameMode) { return(GetSupportedMapsForGameMode(gameMode.GetType().Name)); }