Example #1
0
        public static ModMetadata ReadFromFile(string metaFile, string hashFile, string modFile)
        {
            //Check for hash mismatch
            if (!File.Exists(hashFile))
            {
                GenerateHashForMod(modFile, hashFile);
            }
            bool isMatch = CompareHashes(modFile, hashFile);

            string text = File.ReadAllText(metaFile);

            ModMetadata meta = new ModMetadata();

            Deserializer    ds       = new Deserializer();
            ModJSONMetadata jsonMeta = ds.Deserialize <ModJSONMetadata>(text);

            meta.isEnabled    = jsonMeta.isEnabled;
            meta.isPatch      = jsonMeta.isPatch;
            meta.isDirty      = isMatch;
            meta.isStandalone = jsonMeta.isStandalone;

            meta.modifiedClasses = new Dictionary <string, HashSet <string> >();
            foreach (KeyValuePair <string, List <string> > kvp in jsonMeta.modifiedClasses)
            {
                meta.modifiedClasses[kvp.Key] = new HashSet <string>(kvp.Value);
            }

            meta.modPath = modFile;

            return(meta);
        }
Example #2
0
        public static void SaveMod(ModMetadata md)
        {
            string metaFilePath = Path.Combine(Directory.GetParent(md.modPath).FullName, Path.GetFileNameWithoutExtension(md.modPath) + ".modMeta");
            string hashFilePath = Path.Combine(Directory.GetParent(md.modPath).FullName, Path.GetFileNameWithoutExtension(md.modPath) + ".modHash");

            GenerateHashForMod(md.modPath, hashFilePath);
            WriteToFile(md, metaFilePath);
        }
        public static void LoadModMetas()
        {
            modMetas.Clear();
            string gameDirectory = Directory.GetParent(exePath).FullName;
            string managedPath   = Path.Combine(gameDirectory, Path.GetFileNameWithoutExtension(exePath) + "_Data", "Managed");

            //Load mods
            string modFolder          = Path.Combine(gameDirectory, "Mods");
            string dependenciesFolder = Path.Combine(gameDirectory, "ModDependencies");
            string hashesFolder       = Path.Combine(gameDirectory, "PartialityHashes");
            string oldMetaChecker     = Path.Combine(gameDirectory, "PartialityHashes", "newMeta");

            if (!Directory.Exists(modFolder))
            {
                File.Create(Path.Combine(Directory.CreateDirectory(modFolder).FullName, "mods go here")).Dispose();
            }
            if (!Directory.Exists(dependenciesFolder))
            {
                File.Create(Path.Combine(Directory.CreateDirectory(dependenciesFolder).FullName, "mod dependencies go here")).Dispose();
            }
            if (!Directory.Exists(hashesFolder))
            {
                File.Create(Path.Combine(Directory.CreateDirectory(hashesFolder).FullName, "IGNORE THIS FOLDER! It's just data for Partiality!")).Dispose();
            }

            if (!File.Exists(oldMetaChecker))
            {
                ClearMetas(true);
                File.Create(oldMetaChecker);
                DebugLogger.Log("Clearing old metadata files!");
            }

            string[] files = Directory.GetFiles(modFolder);
            foreach (string s in files)
            {
                DebugLogger.Log("Checking if file is mod " + s);
                if (Path.GetExtension(s) == ".dll")
                {
                    try {
                        ModMetadata md = ModMetadata.GetForMod(s);
                        if (md.isStandalone)
                        {
                            modMetas.Insert(0, md);
                        }
                        else
                        {
                            modMetas.Add(md);
                        }
                    } catch (Exception e) {
                        DebugLogger.Log(e);
                    }
                }
            }

            DebugLogger.Log("Loaded metadata for " + modMetas.Count + " mods");
        }
        public static void SaveAllMetadata()
        {
            string mainPath  = Directory.GetParent(exePath).FullName;
            string modFolder = Path.Combine(mainPath, "Patches");

            foreach (ModMetadata md in modMetas)
            {
                ModMetadata.SaveMod(md);
            }
        }
Example #5
0
        public void SetModEnabled(CheckBox box, int index)
        {
            ModIncompatibilityWarning warningLevel = GameManager.CheckForModIncompatibilities(index);
            ModMetadata md       = GameManager.modMetas[index];
            string      fileName = Path.GetFileName(md.modPath);

            if (md.isStandalone)
            {
                int i = 0;

                foreach (ModMetadata oMD in GameManager.modMetas)
                {
                    if (oMD != md && oMD.isStandalone)
                    {
                        oMD.isStandalone = false;
                        ((modList.Items[i].Control as StackLayout).Items[1].Control as CheckBox).Checked = false;
                    }
                    i++;
                }
            }

            if (md.isEnabled == false)
            {
                if (warningLevel.warningLevel == 1)
                {
                    MessageBox.Show(string.Format("The mod {0} might not work with the following mods:{1}{2}", fileName, Environment.NewLine, warningLevel.sameClassMods));
                }
                else if (warningLevel.warningLevel == 2)
                {
                    string msg = string.Format("The mod {0} is incompatible with the following mods:{1}{2}{1}Don't expect them both to work together, but you can still launch the game.", fileName, Environment.NewLine, warningLevel.sameFunctionMods);
                    if (warningLevel.sameClassMods.Length > 0)
                    {
                        msg += string.Format("It also might not work with these mods:{0}{1}", Environment.NewLine, warningLevel.sameClassMods);
                    }
                    MessageBox.Show(msg);
                }
            }

            md.isEnabled = !md.isEnabled;
        }
        public static void ClearMetas(bool force = false)
        {
            string gameDirectory = Directory.GetParent(exePath).FullName;
            string modFolder     = Path.Combine(gameDirectory, "Mods");
            string hashesFolder  = Path.Combine(gameDirectory, "PartialityHashes");

            string[] modFiles    = Directory.GetFiles(modFolder);
            string[] hashesFiles = Directory.GetFiles(hashesFolder);

            foreach (string s in modFiles)
            {
                string extension = Path.GetExtension(s);
                if (extension == ".modMeta")
                {
                    if (force)
                    {
                        File.Delete(s);
                    }
                    else
                    {
                        ModMetadata md = ModMetadata.ReadRawFromFile(s);

                        if (md.isStandalone == false)
                        {
                            File.Delete(s);
                        }
                    }
                }
                else if (extension == ".modHash")
                {
                    File.Delete(s);
                }
            }

            foreach (string s in hashesFiles)
            {
                File.Delete(s);
            }
        }
Example #7
0
        public static void WriteToFile(ModMetadata meta, string path)
        {
            ModJSONMetadata JSON = new ModJSONMetadata()
            {
                isDirty         = meta.isDirty,
                isEnabled       = meta.isEnabled,
                isPatch         = meta.isPatch,
                isStandalone    = meta.isStandalone,
                modifiedClasses = new Dictionary <string, List <string> >()
            };

            foreach (KeyValuePair <string, HashSet <string> > kvp in meta.modifiedClasses)
            {
                HashSet <string> modClassList = kvp.Value;
                JSON.modifiedClasses[kvp.Key] = new List <string>(modClassList);
            }

            Serializer s    = new Serializer();
            string     json = s.Serialize(JSON);

            File.WriteAllText(path, json);
        }
Example #8
0
        public static ModMetadata ReadRawFromFile(string metaFile)
        {
            string text = File.ReadAllText(metaFile);

            ModMetadata meta = new ModMetadata();

            Deserializer    ds       = new Deserializer();
            ModJSONMetadata jsonMeta = ds.Deserialize <ModJSONMetadata>(text);

            meta.isEnabled    = jsonMeta.isEnabled;
            meta.isPatch      = jsonMeta.isPatch;
            meta.isDirty      = jsonMeta.isDirty;
            meta.isStandalone = jsonMeta.isStandalone;

            meta.modifiedClasses = new Dictionary <string, HashSet <string> >();
            foreach (KeyValuePair <string, List <string> > kvp in jsonMeta.modifiedClasses)
            {
                meta.modifiedClasses[kvp.Key] = new HashSet <string>(kvp.Value);
            }

            return(meta);
        }
        public static ModIncompatibilityWarning CheckForModIncompatibilities(int modIndex)
        {
            ModIncompatibilityWarning warning = new ModIncompatibilityWarning();

            ModMetadata checkMod = modMetas[modIndex];

            StringBuilder warningBuilder      = new StringBuilder();
            StringBuilder incompatibleBuilder = new StringBuilder();

            //If the mod's not a patch, we don't have to care what it messes with.
            if (!checkMod.isPatch)
            {
                return(warning);
            }

            int warnType = 0;

            //Compare the mod to all other mods
            for (int i = 0; i < modMetas.Count; i++)
            {
                if (i == modIndex)
                {
                    continue;
                }

                //Get the other mod we're comparing to
                ModMetadata otherMod = modMetas[i];

                if (!otherMod.isPatch || !otherMod.isEnabled)
                {
                    continue;
                }

                //The warning type will be nothing by default

                //Check all the classes the other mod modifies
                foreach (KeyValuePair <string, HashSet <string> > otherModClass in otherMod.modifiedClasses)
                {
                    //If the other mod modifies a class that this mod does
                    if (checkMod.modifiedClasses.ContainsKey(otherModClass.Key))
                    {
                        //Store this mod's compares for later
                        HashSet <string> classCompare  = checkMod.modifiedClasses[otherModClass.Key];
                        bool             isHighWarning = false;
                        //Set warning type to 1
                        if (warnType == 0)
                        {
                            warnType = 1;
                        }

                        //Check all the functions the other mod changes
                        foreach (string s in otherModClass.Value)
                        {
                            //If both mods change the same function, it as incompatible.
                            if (classCompare.Contains(s))
                            {
                                warnType      = 2;
                                isHighWarning = true;
                                break;
                            }
                        }

                        if (isHighWarning)
                        {
                            incompatibleBuilder.AppendLine(Path.GetFileName(otherMod.modPath));
                        }
                        else
                        {
                            warningBuilder.AppendLine(Path.GetFileName(otherMod.modPath));
                        }

                        break;
                    }
                }
            }

            warning.warningLevel     = warnType;
            warning.sameClassMods    = warningBuilder.ToString();
            warning.sameFunctionMods = incompatibleBuilder.ToString();

            return(warning);
        }
Example #10
0
        public static ModMetadata GenerateForMod(string modFile)
        {
            ModMetadata meta = new ModMetadata();

            meta.isEnabled = false;
            meta.modPath   = modFile;
            ModuleDefinition             modDef   = ModuleDefinition.ReadModule(modFile);
            IEnumerable <TypeDefinition> getTypes = modDef.GetTypes();

            Type   patchType        = typeof(MonoMod.MonoModPatch);
            Type   constructorType  = typeof(MonoMod.MonoModConstructor);
            Type   originalNameType = typeof(MonoMod.MonoModOriginalName);
            Type   ignoreType       = typeof(MonoMod.MonoModIgnore);
            string origPrefix       = "orig_";

            DebugLogger.Log(string.Empty);
            DebugLogger.Log("Generating metadata for " + Path.GetFileName(modFile));

            //Foreach type in the mod dll
            foreach (TypeDefinition checkType in getTypes)
            {
                //If the type has a custom attribute
                if (checkType.HasCustomAttributes)
                {
                    HashSet <CustomAttribute> attributes = new HashSet <CustomAttribute>(checkType.CustomAttributes);
                    //Foreach custom attribute
                    foreach (CustomAttribute ct in attributes)
                    {
                        try
                        {
                            //If the attribute is [MonoModPatch]
                            if (ct.AttributeType.Name == patchType.Name)
                            {
                                string           originalClassName = ct.ConstructorArguments[0].Value as string;
                                HashSet <string> changedFunctions  = new HashSet <string>();

                                DebugLogger.Log(string.Empty);
                                DebugLogger.Log("Adding " + originalClassName);

                                List <MethodDefinition> methods = new List <MethodDefinition>(checkType.Methods);
                                //Foreach method in this type
                                foreach (MethodDefinition methodDef in methods)
                                {
                                    if (methodDef.IsConstructor)
                                    {
                                        continue;
                                    }

                                    if (methodDef.Name.StartsWith(origPrefix))
                                    {
                                        string methodEntry = originalClassName + "->" + methodDef.Name.Remove(0, origPrefix.Length);
                                        DebugLogger.Log("Adding method " + methodEntry);
                                        changedFunctions.Add(methodEntry);
                                    }
                                    else if (methodDef.HasCustomAttributes)
                                    {
                                        HashSet <CustomAttribute> methodAttributes = new HashSet <CustomAttribute>(methodDef.CustomAttributes);
                                        //Foreach custom attribute on the method
                                        foreach (CustomAttribute c in methodAttributes)
                                        {
                                            if (c.AttributeType.Name == ignoreType.Name)
                                            {
                                                string methodEntry = originalClassName + "->" + methodDef.Name;
                                                DebugLogger.Log("Ignoring Method " + methodEntry);
                                                break;
                                            }
                                            else if (c.AttributeType.Name == constructorType.Name)
                                            {
                                                string methodEntry = originalClassName + "->" + "ctor_" + originalClassName;
                                                DebugLogger.Log("Adding Constructor " + methodEntry);
                                                changedFunctions.Add(methodEntry);
                                                break;
                                            }
                                            else if (c.AttributeType.Name == originalNameType.Name)
                                            {
                                                string methodEntry = originalClassName + "->" + methodDef.Name;
                                                DebugLogger.Log("Adding Original Method " + methodEntry);
                                                changedFunctions.Add(methodEntry);
                                                break;
                                            }
                                        }
                                    }
                                }

                                meta.modifiedClasses.Add(originalClassName, changedFunctions);

                                //We're done looking through attributes of this class, break
                                break;
                            }
                        }
                        catch (System.Exception e)
                        {
                            DebugLogger.Log(e);
                        }
                    }
                }
            }

            meta.isPatch = meta.modifiedClasses.Count > 0;
            if (meta.isPatch)
            {
                meta.isDirty = true;
            }

            modDef.Dispose();

            return(meta);
        }
Example #11
0
        public static void PatchGame()
        {
            string executablePath      = Assembly.GetEntryAssembly().Location;
            string executableDirectory = Directory.GetParent(executablePath).FullName;
            string monoModPath         = Path.Combine(executableDirectory, "MonoMod.exe");
            string hookGenPath         = Path.Combine(executableDirectory, "MonoMod.RuntimeDetour.HookGen.exe");
            string runtimeDetourDLL    = "MonoMod.RuntimeDetour.dll";
            string mmUtilsDLL          = "MonoMod.Utils.dll";
            string jsonDLL             = "YamlDotNet.dll";

            string gameDirectory   = Directory.GetParent(GameManager.exePath).FullName;
            string hashesFolder    = Path.Combine(gameDirectory, "PartialityHashes");
            string modDependencies = Path.Combine(gameDirectory, "ModDependencies");
            string dataDirectory   = Path.Combine(gameDirectory, Path.GetFileNameWithoutExtension(GameManager.exePath) + "_Data");
            string managedFolder   = Path.Combine(dataDirectory, "Managed");
            string codeDll         = Path.Combine(managedFolder, "Assembly-CSharp.dll");
            string hookGenDLL      = Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll");
            string engineDll       = Path.Combine(managedFolder, "UnityEngine.dll");
            string coreModuleDLL   = Path.Combine(managedFolder, "UnityEngine.CoreModule.dll");

            string backupFolder = managedFolder + "_backup";

            Process currentProcess = Process.GetCurrentProcess();
            Process monomodProcess = new Process();

            monomodProcess.StartInfo.FileName               = monoModPath;
            monomodProcess.StartInfo.CreateNoWindow         = true;
            monomodProcess.StartInfo.UseShellExecute        = false;
            monomodProcess.StartInfo.RedirectStandardOutput = true;

            //Create backup if there isn't one
            if (!Directory.Exists(backupFolder))
            {
                Directory.CreateDirectory(backupFolder);
                CopyFilesRecursively(managedFolder, backupFolder);
            }

            GameManager.CreatePartialityDirectories();

            //Install the default patch for PartialityLauncher
            {
                string engineDLLName = "UnityEngine.dll";

                if (File.Exists(coreModuleDLL))
                {
                    engineDLLName = "UnityEngine.CoreModule.dll";
                    engineDll     = coreModuleDLL;
                }

                string moddedDLL             = Path.Combine(Path.GetDirectoryName(engineDll), "patched" + engineDLLName);
                string defaultPatchLocation  = Path.Combine(executableDirectory, "PartialityPatch.dll");
                string partialityModLocation = Path.Combine(Path.GetDirectoryName(engineDll), "Partiality.dll");

                bool shouldPatch = false;

                if (!File.Exists(Path.Combine(hashesFolder, "ENGINEHASH.hash")))
                {
                    shouldPatch = true;
                }
                else
                {
                    shouldPatch = !ModMetadata.CompareHashes(defaultPatchLocation, Path.Combine(hashesFolder, "ENGINEHASH.hash"));
                }

                //Delete mod if it exists
                if (File.Exists(partialityModLocation))
                {
                    File.Delete(partialityModLocation);
                }
                //Copy mod to folder with assembly-chsharp.dll
                File.Copy(Path.Combine(executableDirectory, "Partiality.dll"), partialityModLocation);

                if (shouldPatch)
                {
                    //Restore backup
                    File.Delete(engineDll);
                    File.Copy(Path.Combine(backupFolder, engineDLLName), engineDll);

                    //Set monomod arguments to "[UnityEngine.dll] [PartialityPatch.dll] [patched_UnityEngine.dll]"

                    //monomodProcess.StartInfo.Arguments = ('"' + engineDll + '"') + " " + ('"' + defaultPatchLocation + '"') + " " + ('"' + moddedDLL + '"');
                    monomodProcess.StartInfo.Arguments = $"\"{engineDll}\" \"{defaultPatchLocation}\" \"{moddedDLL}\"";

                    monomodProcess.Start();
                    string mmoutput = monomodProcess.StandardOutput.ReadToEnd();

                    DebugLogger.Log(mmoutput);
                    Console.WriteLine(mmoutput);
                    monomodProcess.WaitForExit();

                    int exitCode = monomodProcess.ExitCode;
                    Console.WriteLine("MMEC:" + exitCode);
                    Console.WriteLine(mmoutput);

                    //Replace file
                    if (File.Exists(moddedDLL))
                    {
                        //Move modded .dll over original .dll
                        File.Delete(engineDll);
                        File.Copy(moddedDLL, engineDll);
                        File.Delete(moddedDLL);
                    }

                    byte[] newHash = ChecksumHasher.ComputeHash(File.ReadAllBytes(defaultPatchLocation));
                    File.WriteAllBytes(Path.Combine(hashesFolder, "ENGINEHASH.hash"), newHash);
                }
            }

            //Install custom patches
            {
                string[] files = Directory.GetFiles(modDependencies);


                //Copy mod dependencies
                foreach (string dependency in files)
                {
                    string fileName = Path.GetFileName(dependency);
                    //Delete the dependency if it already exists
                    if (File.Exists(Path.Combine(managedFolder, fileName)))
                    {
                        File.Delete(Path.Combine(managedFolder, fileName));
                    }
                    //Copy the file
                    File.Copy(dependency, Path.Combine(managedFolder, fileName));
                }

                bool   shouldPatch    = false;
                string moddedDLL      = Path.Combine(Path.GetDirectoryName(engineDll), "patched_Assembly-CSharp.dll");
                string epListLocation = Path.Combine(hashesFolder, "ENABLEDPATCHES.enp");


                //Check if we have the same enabled/disabled mods as last time, if we do, then
                {
                    string totalEnabledPatches = "Partiality+";
                    foreach (ModMetadata md in GameManager.modMetas)
                    {
                        if ((md.isStandalone || md.isPatch) && md.isEnabled)
                        {
                            totalEnabledPatches += Path.GetFileNameWithoutExtension(md.modPath) + "+";
                        }
                    }

                    DebugLogger.Log(totalEnabledPatches);

                    if (File.Exists(epListLocation))
                    {
                        string getList = File.ReadAllText(epListLocation);
                        shouldPatch = getList != totalEnabledPatches;
                        if (shouldPatch)
                        {
                            File.WriteAllText(epListLocation, totalEnabledPatches);
                        }
                    }
                    else
                    {
                        shouldPatch = true;
                        File.WriteAllText(epListLocation, totalEnabledPatches);
                    }
                }

                //If all the same mods are enabled, check if any mods are dirty. If they are, we gotta re-patch.
                if (!shouldPatch)
                {
                    foreach (ModMetadata md in GameManager.modMetas)
                    {
                        if (md.isDirty)
                        {
                            shouldPatch = true;
                            break;
                        }
                    }
                }

                if (shouldPatch)
                {
                    DebugLogger.Log("Patching Assembly-CSharp");

                    string backupDll = Path.Combine(backupFolder, "Assembly-CSharp.dll");

                    foreach (ModMetadata md in GameManager.modMetas)
                    {
                        if (md.isStandalone && md.isEnabled)
                        {
                            backupDll = md.modPath;
                        }
                    }

                    //Restore backup
                    File.Delete(codeDll);
                    File.Copy(backupDll, codeDll);

                    List <string> failedPatches = new List <string>();

                    foreach (ModMetadata md in GameManager.modMetas)
                    {
                        if (md.isPatch && md.isEnabled)
                        {
                            //monomodProcess.StartInfo.Arguments = ('"' + codeDll + '"') + " " + ('"' + md.modPath + '"') + " " + ('"' + moddedDLL + '"');
                            monomodProcess.StartInfo.Arguments = $"\"{codeDll}\" \"{md.modPath}\" \"{moddedDLL}\"";

                            monomodProcess.Start();
                            monomodProcess.WaitForExit();
                            string mmoutput = monomodProcess.StandardOutput.ReadToEnd();

                            int exitCode = monomodProcess.ExitCode;
                            DebugLogger.Log("MMEC:" + exitCode);
                            DebugLogger.Log(mmoutput);

                            if (exitCode != 0)
                            {
                                failedPatches.Add(Path.GetFileNameWithoutExtension(md.modPath));
                            }

                            //Replace file
                            if (File.Exists(moddedDLL))
                            {
                                //Move modded .dll over original .dll
                                File.Delete(codeDll);
                                File.Copy(moddedDLL, codeDll);
                                File.Delete(moddedDLL);
                            }
                        }
                    }

                    if (failedPatches.Count > 0)
                    {
                        MessageBox.Show("Some mods failed to apply correctly! Please send your LOG.txt (in the Partiality folder) to someone who can help, probably from the people who made the mod.");
                    }

                    //Set mods to all not be dirty, and save them.
                    foreach (ModMetadata md in GameManager.modMetas)
                    {
                        md.isDirty = false;
                    }

                    try
                    {
                        GameManager.SaveAllMetadata();
                    }
                    catch (System.Exception e)
                    {
                        DebugLogger.Log(e);
                    }
                }
            }

            //HookGen stuff
            {
                //Delete Legacy DLL
                if (File.Exists(Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll")))
                {
                    File.Delete(Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll"));
                }

                if (File.Exists(hookGenDLL))
                {
                    File.Delete(hookGenDLL);
                }

                //Delete files if they existed, so we can update them.
                if (File.Exists(Path.Combine(managedFolder, runtimeDetourDLL)))
                {
                    File.Delete(Path.Combine(managedFolder, runtimeDetourDLL));
                }
                if (File.Exists(Path.Combine(managedFolder, mmUtilsDLL)))
                {
                    File.Delete(Path.Combine(managedFolder, mmUtilsDLL));
                }
                if (File.Exists(Path.Combine(managedFolder, jsonDLL)))
                {
                    File.Delete(Path.Combine(managedFolder, jsonDLL));
                }

                //Copy files
                File.Copy(Path.Combine(executableDirectory, runtimeDetourDLL), Path.Combine(managedFolder, runtimeDetourDLL));
                File.Copy(Path.Combine(executableDirectory, mmUtilsDLL), Path.Combine(managedFolder, mmUtilsDLL));
                File.Copy(Path.Combine(executableDirectory, jsonDLL), Path.Combine(managedFolder, jsonDLL));

                string pathIn  = codeDll;
                string pathOut = hookGenDLL;

                using (MonoModder mm = new MonoModder
                {
                    InputPath = pathIn,
                    OutputPath = pathOut
                })
                {
                    mm.Read();
                    mm.MapDependencies();
                    if (File.Exists(pathOut))
                    {
                        mm.Log(string.Format("Clearing {0}", pathOut));
                        File.Delete(pathOut);
                    }
                    mm.Log("[HookGen] Starting HookGenerator");
                    HookGenerator gen = new HookGenerator(mm, Path.GetFileName(pathOut));
                    using (ModuleDefinition mOut = gen.OutputModule)
                    {
                        gen.HookPrivate = true;
                        gen.Generate();
                        mOut.Write(pathOut);
                    }
                    mm.Log("[HookGen] Done.");
                }
            }

            //File.WriteAllText( gameDirectory + "\\PARTIALITY_OUTPUT.txt", );
        }