/// <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;
		}
예제 #2
0
        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));
                    }
                }
            }
        }
예제 #3
0
        /// <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);
 }
예제 #5
0
        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));
 }