コード例 #1
0
        private async void Menu_Backup_Click(object sender, RoutedEventArgs e)
        {
            var result = FlexibleMessageBox.Show("This will create a backup of the index files TexTools can modify (01, 04, 06)\n\n" +
                                                 "Do you want to Backup Now?" +
                                                 "\n\nWarning:\nIn order to create a clean backup, all active modifications will be set to disabled, they will have to be re-enabled manually.",
                                                 "Backup Index Files", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                var gameDirectory   = new DirectoryInfo(Settings.Default.FFXIV_Directory);
                var backupDirectory = new DirectoryInfo(Properties.Settings.Default.Backup_Directory);
                var indexFiles      = new XivDataFile[] { XivDataFile._04_Chara, XivDataFile._06_Ui, XivDataFile._01_Bgcommon };
                var index           = new Index(gameDirectory);
                var modding         = new Modding(gameDirectory);

                if (index.IsIndexLocked(XivDataFile._0A_Exd))
                {
                    FlexibleMessageBox.Show("Unable to create backup while game is running.", $"Backup Creation Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                try
                {
                    // Toggle off all mods
                    modding.ToggleAllMods(false);
                }
                catch (Exception ex)
                {
                    FlexibleMessageBox.Show($"Unable to create backup files.\n\nError Message:\n{ex.Message}", $"Backup Creation Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                foreach (var xivDataFile in indexFiles)
                {
                    try
                    {
                        File.Copy($"{gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index",
                                  $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index", true);
                        File.Copy($"{gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index2",
                                  $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index2", true);
                    }
                    catch (Exception ex)
                    {
                        FlexibleMessageBox.Show($"Unable to create backups.\n\nError: {ex.Message}", $"Backup Creation Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                await this.ShowMessageAsync("Backup Complete", "The index files have been successfully backed up");
            }
        }
コード例 #2
0
        private async void Menu_Backup_Click(object sender, RoutedEventArgs e)
        {
            var result = FlexibleMessageBox.Show(UIMessages.CreateBackupsMessage, UIMessages.CreateBackupsTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Information);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                var gameDirectory   = new DirectoryInfo(Settings.Default.FFXIV_Directory);
                var backupDirectory = new DirectoryInfo(Properties.Settings.Default.Backup_Directory);
                var indexFiles      = new XivDataFile[] { XivDataFile._04_Chara, XivDataFile._06_Ui, XivDataFile._01_Bgcommon };
                var index           = new Index(gameDirectory);
                var modding         = new Modding(gameDirectory);

                if (index.IsIndexLocked(XivDataFile._0A_Exd))
                {
                    FlexibleMessageBox.Show(UIMessages.IndexLockedBackupFailedMessage, UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                try
                {
                    // Toggle off all mods
                    await modding.ToggleAllMods(false);
                }
                catch (Exception ex)
                {
                    FlexibleMessageBox.Show(string.Format(UIMessages.BackupFailedErrorMessage, ex.Message), UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                foreach (var xivDataFile in indexFiles)
                {
                    try
                    {
                        File.Copy($"{gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index",
                                  $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index", true);
                        File.Copy($"{gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index2",
                                  $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index2", true);
                    }
                    catch (Exception ex)
                    {
                        FlexibleMessageBox.Show(string.Format(UIMessages.BackupFailedErrorMessage, ex.Message), UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                await this.ShowMessageAsync(UIMessages.BackupCompleteTitle, UIMessages.BackupCompleteMessage);
            }
        }
コード例 #3
0
        public Task BackupIndexFiles(DirectoryInfo backupsDirectory)
        {
            return(Task.Run(async() => {
                var indexFiles = new XivDataFile[] { XivDataFile._0A_Exd, XivDataFile._04_Chara, XivDataFile._06_Ui, XivDataFile._01_Bgcommon };
                var index = new Index(_gameDirectory);
                var modding = new Modding(_gameDirectory);

                if (index.IsIndexLocked(XivDataFile._0A_Exd))
                {
                    throw new Exception("Index files are in use by another process.");
                }

                try
                {
                    // Toggle off all mods
                    await modding.ToggleAllMods(false);
                }
                catch
                {
                    throw new Exception("Failed to disable mods.\n\n" +
                                        "Please check For problems by selecting Help -> Check For Problems");
                }


                var originalFiles = Directory.GetFiles(_gameDirectory.FullName);
                foreach (var originalFile in originalFiles)
                {
                    try
                    {
                        if (originalFile.Contains(".win32.index"))
                        {
                            File.Copy(originalFile, $"{backupsDirectory}/{Path.GetFileName(originalFile)}", true);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Failed to copy index files.\n\n" + ex.Message);
                    }
                }
            }));
        }
コード例 #4
0
        private Task CheckGameVersion()
        {
            return(Task.Run(async() =>
            {
                var applicationVersion = FileVersionInfo
                                         .GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;

                Version ffxivVersion = null;
                var needsNewBackup = false;
                var backupMessage = "";

                var modding = new Modding(_gameDirectory);
                var backupDirectory = new DirectoryInfo(Properties.Settings.Default.Backup_Directory);

                var versionFile = $"{_gameDirectory.Parent.Parent.FullName}\\ffxivgame.ver";

                if (File.Exists(versionFile))
                {
                    var versionData = File.ReadAllLines(versionFile);
                    ffxivVersion = new Version(versionData[0].Substring(0, versionData[0].LastIndexOf(".")));
                }
                else
                {
                    FlexibleMessageBox.Show(_win32Window, UIMessages.GameVersionErrorMessage,
                                            string.Format(UIMessages.GameVersionErrorTitle, applicationVersion), MessageBoxButtons.OK,
                                            MessageBoxIcon.Warning);
                    return;
                }

                if (string.IsNullOrEmpty(Properties.Settings.Default.FFXIV_Version))
                {
                    Properties.Settings.Default.FFXIV_Version = ffxivVersion.ToString();
                    Properties.Settings.Default.Save();

                    needsNewBackup = true;
                    backupMessage = UIMessages.NewInstallDetectedBackupMessage;
                }
                else
                {
                    var versionCheck = new Version(Properties.Settings.Default.FFXIV_Version);

                    if (ffxivVersion > versionCheck)
                    {
                        needsNewBackup = true;
                        backupMessage = UIMessages.NewerVersionDetectedBackupMessage;
                    }
                }

                if (!Directory.Exists(backupDirectory.FullName))
                {
                    FlexibleMessageBox.Show(_win32Window, UIMessages.BackupsDirectoryErrorMessage, UIMessages.BackupFailedTitle,
                                            MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                if (Directory.GetFiles(backupDirectory.FullName).Length == 0)
                {
                    needsNewBackup = true;
                    backupMessage = UIMessages.NoBackupsFoundMessage;
                }

                if (needsNewBackup)
                {
                    var indexFiles = new XivDataFile[]
                    { XivDataFile._04_Chara, XivDataFile._06_Ui, XivDataFile._01_Bgcommon };

                    if (FlexibleMessageBox.Show(_win32Window, backupMessage, UIMessages.CreateBackupTitle, MessageBoxButtons.YesNo,
                                                MessageBoxIcon.Warning) == DialogResult.Yes)
                    {
                        if (_index.IsIndexLocked(XivDataFile._0A_Exd))
                        {
                            FlexibleMessageBox.Show(_win32Window, UIMessages.IndexLockedBackupFailedMessage,
                                                    UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            return;
                        }

                        try
                        {
                            // Toggle off all mods
                            await modding.ToggleAllMods(false);
                        }
                        catch (Exception ex)
                        {
                            FlexibleMessageBox.Show(_win32Window, string.Format(UIMessages.BackupFailedErrorMessage, ex.Message),
                                                    UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            return;
                        }

                        foreach (var xivDataFile in indexFiles)
                        {
                            try
                            {
                                File.Copy($"{_gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index",
                                          $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index", true);
                                File.Copy($"{_gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index2",
                                          $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index2", true);
                            }
                            catch (Exception e)
                            {
                                FlexibleMessageBox.Show(_win32Window, string.Format(UIMessages.BackupFailedErrorMessage, e.Message),
                                                        UIMessages.BackupFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }

                        Properties.Settings.Default.FFXIV_Version = ffxivVersion.ToString();
                        Properties.Settings.Default.Save();
                    }
                }
            }));
        }
コード例 #5
0
        private void CheckGameVersion()
        {
            var applicationVersion = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;

            Version ffxivVersion   = null;
            var     needsNewBackup = false;
            var     backupMessage  = "";

            var modding         = new Modding(_gameDirectory);
            var backupDirectory = new DirectoryInfo(Properties.Settings.Default.Backup_Directory);

            var versionFile = $"{_gameDirectory.Parent.Parent.FullName}\\ffxivgame.ver";

            if (File.Exists(versionFile))
            {
                var versionData = File.ReadAllLines(versionFile);
                ffxivVersion = new Version(versionData[0].Substring(0, versionData[0].LastIndexOf(".")));
            }
            else
            {
                FlexibleMessageBox.Show("TexTools was unable to determine the game version.", $"Version Check Error {applicationVersion}", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (string.IsNullOrEmpty(Properties.Settings.Default.FFXIV_Version))
            {
                Properties.Settings.Default.FFXIV_Version = ffxivVersion.ToString();
                Properties.Settings.Default.Save();

                needsNewBackup = true;
                backupMessage  = "New TexTools Install Detected. \nWould you like to create a new backup of your index files now? (Recommended)";
            }
            else
            {
                var versionCheck = new Version(Properties.Settings.Default.FFXIV_Version);

                if (ffxivVersion > versionCheck)
                {
                    needsNewBackup = true;
                    backupMessage  = "A newer version of FFXIV was detected. \nWould you like to create a new backup of your index files now? (Recommended) \n\nWarning:\nIn order to create a clean backup, all active modifications will be set to disabled, they will have to be re-enabled manually.";
                }
            }

            if (!Directory.Exists(backupDirectory.FullName))
            {
                FlexibleMessageBox.Show("Unable to find backup directory", $"Backup Creation Failed {applicationVersion}", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (Directory.GetFiles(backupDirectory.FullName).Length == 0)
            {
                needsNewBackup = true;
                backupMessage  = "No Index Backups were found. \nWould you like to create a new backup of your index files now? (Recommended) \n\nWarning:\nIn order to create a clean backup, all active modifications will be set to disabled, they will have to be re-enabled manually.";
            }

            if (needsNewBackup)
            {
                var indexFiles = new XivDataFile[] { XivDataFile._04_Chara, XivDataFile._06_Ui, XivDataFile._01_Bgcommon };
                var index      = new Index(_gameDirectory);

                if (MessageBox.Show(backupMessage, "Create Backup?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) ==
                    DialogResult.Yes)
                {
                    try
                    {
                        // Toggle off all mods
                        modding.ToggleAllMods(false);
                    }
                    catch (Exception ex)
                    {
                        FlexibleMessageBox.Show($"Unable to create backup files.\n\nError Message:\n{ex.Message}", $"Backup Creation Failed {applicationVersion}", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }

                    if (index.IsIndexLocked(XivDataFile._0A_Exd))
                    {
                        FlexibleMessageBox.Show("Unable to create backup while game is running.", $"Backup Creation Failed {applicationVersion}", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }

                    foreach (var xivDataFile in indexFiles)
                    {
                        try
                        {
                            File.Copy($"{_gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index",
                                      $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index", true);
                            File.Copy($"{_gameDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index2",
                                      $"{backupDirectory}\\{xivDataFile.GetDataFileName()}.win32.index2", true);
                        }
                        catch (Exception e)
                        {
                            FlexibleMessageBox.Show($"Unable to create backups.\n\nError: {e.Message}", $"Backup Creation Failed {applicationVersion}", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            }
        }
コード例 #6
0
        public Task PerformStartOver(DirectoryInfo backupsDirectory, IProgress <string> progress = null, XivLanguage language = XivLanguage.None)
        {
            return(Task.Run(async() =>
            {
                var modding = new Modding(_gameDirectory);
                var backupsRestored = false;

                // Stop the cache worker since we're blowing up the entire index file and db anyways.
                // The cache rebuild will start it up again after the cache is rebuilt.
                XivCache.CacheWorkerEnabled = false;

                try
                {
                    // Try restoring the indexes FIRST.
                    backupsRestored = await RestoreBackups(backupsDirectory);
                    progress?.Report("Restoring index file backups...");

                    if (!backupsRestored)
                    {
                        throw new Exception("Start Over Failed: Index backups missing/outdated.");
                    }
                }
                catch (Exception ex)
                {
                    try
                    {
                        // If the index restore failed, try just disabling.
                        await modding.DeleteAllFilesAddedByTexTools();
                        await modding.ToggleAllMods(false);
                        progress?.Report("Index restore failed, attempting to delete all mods instead...");
                    } catch
                    {
                        throw new Exception("Start Over Failed: Index Backups Invalid and Unable to Disable all mods.");
                    }
                }
                finally
                {
                    progress?.Report("Deleting modded dat files...");

                    var dat = new Dat(_gameDirectory);

                    // Delete modded dat files
                    foreach (var xivDataFile in (XivDataFile[])Enum.GetValues(typeof(XivDataFile)))
                    {
                        var datFiles = await dat.GetModdedDatList(xivDataFile);

                        foreach (var datFile in datFiles)
                        {
                            File.Delete(datFile);
                        }

                        if (datFiles.Count > 0)
                        {
                            await RepairIndexDatCounts(xivDataFile);
                        }
                    }

                    progress?.Report("Cleaning up mod list...");

                    var modListDirectory = new DirectoryInfo(Path.Combine(_gameDirectory.Parent.Parent.FullName, XivStrings.ModlistFilePath));

                    // Delete mod list
                    File.Delete(modListDirectory.FullName);

                    modding.CreateModlist();

                    progress?.Report("Rebuilding Cache...");

                    await Task.Run(async() =>
                    {
                        XivCache.RebuildCache();
                    });
                }
            }));
        }
コード例 #7
0
        public Task PerformStartOver(DirectoryInfo backupsDirectory, IProgress <string> progress = null, XivLanguage language = XivLanguage.None)
        {
            return(Task.Run(async() =>
            {
                progress?.Report("Deleting mods...");

                var modding = new Modding(_gameDirectory);
                var backupsRestored = false;

                try
                {
                    // Try to restore the index entries to their original values by deleting any files added by TexTools
                    // and setting mods to disabled
                    await modding.DeleteAllFilesAddedByTexTools();
                    await modding.ToggleAllMods(false);
                    progress?.Report("Restoring index file backups...");
                }
                catch
                {
                    // If an exception occurred due to a corrupted modlist which couldn't be deserealized restore the backup index
                    // files by force
                    backupsRestored = await RestoreBackups(backupsDirectory);

                    if (!backupsRestored)
                    {
                        throw new Exception("Start Over Failed: Index backups missing/outdated.");
                    }
                }
                finally
                {
                    // If no exception occured, restore the backups anyway just to be safe but don't throw an exception if it fails
                    // due to outdated or missing backups since setting back the original index values should be enough hopefully
                    if (!backupsRestored)
                    {
                        backupsRestored = await RestoreBackups(backupsDirectory);

                        // If backups were not restored that means they were missing/outdated so try to make new backups now
                        if (!backupsRestored)
                        {
                            try
                            {
                                await BackupIndexFiles(backupsDirectory);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("Start Over Failed: Failed to update outdated backups.\n\n" + ex.Message);
                            }
                        }
                    }

                    progress?.Report("Deleting modded dat files...");

                    var dat = new Dat(_gameDirectory);

                    // Delete modded dat files
                    foreach (var xivDataFile in (XivDataFile[])Enum.GetValues(typeof(XivDataFile)))
                    {
                        var datFiles = await dat.GetModdedDatList(xivDataFile);

                        foreach (var datFile in datFiles)
                        {
                            File.Delete(datFile);
                        }

                        if (datFiles.Count > 0)
                        {
                            await RepairIndexDatCounts(xivDataFile);
                        }
                    }

                    progress?.Report("Cleaning up mod list...");

                    var modListDirectory = new DirectoryInfo(Path.Combine(_gameDirectory.Parent.Parent.FullName, XivStrings.ModlistFilePath));

                    // Delete mod list
                    File.Delete(modListDirectory.FullName);

                    modding.CreateModlist();

                    progress?.Report("Rebuilding Cache...");

                    await Task.Run(async() =>
                    {
                        var _cache = new XivCache(_gameDirectory, language);
                        _cache.RebuildCache();
                    });
                }
            }));
        }
コード例 #8
0
        /// <summary>
        /// Performs post-patch modlist corrections and validation, prompting user also to generate backups after a successful completion.
        /// </summary>
        /// <returns></returns>
        public async Task DoPostPatchCleanup()
        {
            FlexibleMessageBox.Show(_mainWindow.Win32Window, UIMessages.PatchDetectedMessage, "Post Patch Cleanup Starting", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            MainWindow.MakeHighlander();

            var resetLumina = false;

            await _mainWindow.LockUi("Performing Post-Patch Maintenence", "This may take a few minutes if you have many mods installed.", this);

            var gi = XivCache.GameInfo;

            if (XivCache.GameInfo.UseLumina)
            {
                resetLumina = true;
                XivCache.SetGameInfo(gi.GameDirectory, gi.GameLanguage, gi.DxMode, false, false, gi.LuminaDirectory, gi.UseLumina);
            }

            var workerStatus = XivCache.CacheWorkerEnabled;

            if (workerStatus)
            {
                // Stop the cache worker if it's running.
                XivCache.CacheWorkerEnabled = false;
            }
            try
            {
                var modding = new Modding(_gameDirectory);
                var _index  = new Index(_gameDirectory);
                var _dat    = new Dat(_gameDirectory);

                var validTypes = new List <int>()
                {
                    2, 3, 4
                };

                // We have to do a few things here.
                // 1.  Save a list of what mods were enabled.
                // 2.  Go through and validate everything that says it is enabled actually is enabled, or mark it as disabled and update its original index offset if it is not.
                // 3.  Prompt the user for either a full disable and backup creation, or a restore to normal state (re-enable anything that was enabled before but is not now)
                var modList = modding.GetModList();

                Dictionary <XivDataFile, IndexFile> indexFiles = new Dictionary <XivDataFile, IndexFile>();


                // Cache our currently enabled stuff.
                List <Mod> enabledMods = modList.Mods.Where(x => x.enabled == true).ToList();
                var        toRemove    = new List <Mod>();

                foreach (var mod in modList.Mods)
                {
                    if (!String.IsNullOrEmpty(mod.fullPath))
                    {
                        var df = IOUtil.GetDataFileFromPath(mod.fullPath);
                        if (!indexFiles.ContainsKey(df))
                        {
                            indexFiles[df] = await _index.GetIndexFile(df);
                        }

                        var index1Value       = indexFiles[df].Get8xDataOffset(mod.fullPath);
                        var index2Value       = indexFiles[df].Get8xDataOffsetIndex2(mod.fullPath);
                        var oldOriginalOffset = mod.data.originalOffset;
                        var modOffset         = mod.data.modOffset;


                        // In any event where an offset does not match either of our saved offsets, we must assume this is a new
                        // default file offset for post-patch.
                        if (index1Value != oldOriginalOffset && index1Value != modOffset && index1Value != 0)
                        {
                            // Index 1 value is our new base offset.
                            var type = _dat.GetFileType(index1Value, df);

                            // Make sure the file it's trying to point to is actually valid.
                            if (validTypes.Contains(type))
                            {
                                mod.data.originalOffset = index1Value;
                                mod.enabled             = false;
                            }
                            else
                            {
                                // Oh dear.  The new index is f****d.  Is the old Index Ok?
                                type = _dat.GetFileType(oldOriginalOffset, df);

                                if (validTypes.Contains(type) && oldOriginalOffset != 0)
                                {
                                    // Old index is fine, so keep using that.

                                    // But mark the index value as invalid, so that we stomp on the index value after this.
                                    index1Value = -1;
                                    mod.enabled = false;
                                }
                                else
                                {
                                    // Okay... Maybe the new Index2 Value?
                                    if (index2Value != 0)
                                    {
                                        type = _dat.GetFileType(index2Value, df);
                                        if (validTypes.Contains(type))
                                        {
                                            // Set the index 1 value to invalid so that the if later down the chain stomps the index1 value.
                                            index1Value = -1;

                                            mod.data.originalOffset = index2Value;
                                            mod.enabled             = false;
                                        }
                                        else
                                        {
                                            // We be f****d.
                                            throw new Exception("Unable to determine working original offset for file:" + mod.fullPath);
                                        }
                                    }
                                    else
                                    {
                                        // We be f****d.
                                        throw new Exception("Unable to determine working original offset for file:" + mod.fullPath);
                                    }
                                }
                            }
                        }
                        else if (index2Value != oldOriginalOffset && index2Value != modOffset && index2Value != 0)
                        {
                            // Our Index 1 was normal, but our Index 2 is changed to an unknown value.
                            // If the index 2 points to a valid file, we must assume that this new file
                            // is our new base data offset.

                            var type = _dat.GetFileType(index2Value, df);

                            if (validTypes.Contains(type) && index2Value != 0)
                            {
                                mod.data.originalOffset = index2Value;
                                mod.enabled             = false;
                            }
                            else
                            {
                                // Oh dear.  The new index is f****d.  Is the old Index Ok?
                                type = _dat.GetFileType(oldOriginalOffset, df);

                                if (validTypes.Contains(type) && oldOriginalOffset != 0)
                                {
                                    // Old index is fine, so keep using that, but set the index2 value to invalid to ensure we
                                    // stomp on the current broken index value.
                                    index2Value = -1;
                                }
                                else
                                {
                                    // We be f****d.
                                    throw new Exception("Unable to determine working original offset for file:" + mod.fullPath);
                                }
                            }
                        }

                        // Indexes don't match.  This can occur if SE adds something to index2 that didn't exist in index2 before.
                        if (index1Value != index2Value && index2Value != 0)
                        {
                            // We should never actually get to this state for file-addition mods.  If we do, uh.. I guess correct the indexes and yolo?
                            // ( Only way we get here is if SE added a new file at the same name as a file the user had created via modding, in which case, it's technically no longer a file addition mod )
                            indexFiles[df].SetDataOffset(mod.fullPath, mod.data.originalOffset);
                            index1Value = mod.data.originalOffset;
                            index2Value = mod.data.originalOffset;

                            mod.enabled = false;
                        }

                        // Set it to the corrected state.
                        if (index1Value == mod.data.modOffset)
                        {
                            mod.enabled = true;
                        }
                        else
                        {
                            mod.enabled = false;
                        }

                        // Perform a basic file type check on our results.
                        var fileType         = _dat.GetFileType(mod.data.modOffset, IOUtil.GetDataFileFromPath(mod.fullPath));
                        var originalFileType = _dat.GetFileType(mod.data.modOffset, IOUtil.GetDataFileFromPath(mod.fullPath));

                        if (!validTypes.Contains(fileType) || mod.data.modOffset == 0)
                        {
                            // Mod data is busted.  Fun.
                            toRemove.Add(mod);
                        }

                        if ((!validTypes.Contains(originalFileType)) || mod.data.originalOffset == 0)
                        {
                            if (mod.IsCustomFile())
                            {
                                // Okay, in this case this is recoverable as the mod is a custom addition anyways, so we can just delete it.
                                if (!toRemove.Contains(mod))
                                {
                                    toRemove.Add(mod);
                                }
                            }
                            else
                            {
                                // Update ended up with us unable to find a working offset.  Double fun.
                                throw new Exception("Unable to determine working offset for file:" + mod.fullPath);
                            }
                        }
                    }

                    // Okay, this mod is now represented in the modlist in it's actual post-patch index state.
                    var datNum = (int)((mod.data.modOffset / 8) & 0x0F) / 2;
                    var dat    = XivDataFiles.GetXivDataFile(mod.datFile);

                    var originalDats = await _dat.GetUnmoddedDatList(dat);

                    var datPath = $"{dat.GetDataFileName()}{Dat.DatExtension}{datNum}";

                    // Test for SE Dat file rollover.
                    if (originalDats.Contains(datPath))
                    {
                        // Shit.  This means that the dat file where this mod lived got eaten by SE.  We have to destroy the modlist entry at this point.
                        toRemove.Add(mod);
                    }
                }

                // Save any index changes we made.
                foreach (var dkv in indexFiles)
                {
                    await _index.SaveIndexFile(dkv.Value);
                }

                // The modlist is now saved in its current index-represented post patch state.
                modding.SaveModList(modList);

                // We now need to clear out any mods that are irreparably f****d, and clear out all of our
                // internal data files so we can rebuild them later.

                var internalFiles = modList.Mods.Where(x => x.IsInternal());
                toRemove.AddRange(internalFiles);

                if (toRemove.Count > 0)
                {
                    var removedString = "";

                    // Soft-Disable all metadata mods, since we're going to purge their internal file entries.
                    var metadata = modList.Mods.Where(x => x.fullPath.EndsWith(".meta") || x.fullPath.EndsWith(".rgsp"));
                    foreach (var mod in metadata)
                    {
                        var df = IOUtil.GetDataFileFromPath(mod.fullPath);
                        await modding.ToggleModUnsafe(false, mod, true, false, indexFiles[df], modList);
                    }

                    foreach (var mod in toRemove)
                    {
                        if (mod.data.modOffset == 0 || mod.data.originalOffset == 0)
                        {
                            if (mod.data.originalOffset == 0 && mod.enabled)
                            {
                                // This is awkward.  We have a mod whose data got bashed, but has no valid original offset to restore.
                                // So the indexes here are f****d if we do, f****d if we don't.
                                throw new Exception("Patch-Broken file has no valid index to restore.  Clean Index Restoration required.");
                            }

                            modList.Mods.Remove(mod);
                            enabledMods.Remove(mod);
                            removedString += mod.fullPath + "\n";
                        }
                        else
                        {
                            if (mod.enabled)
                            {
                                var df = IOUtil.GetDataFileFromPath(mod.fullPath);
                                await modding.ToggleModUnsafe(false, mod, true, false, indexFiles[df], modList);
                            }

                            modList.Mods.Remove(mod);

                            // Since we're deleting this entry entirely, we can't leave it in the other cached list either to get re-enabled later.
                            enabledMods.Remove(mod);

                            if (!mod.IsInternal())
                            {
                                removedString += mod.fullPath + "\n";
                            }
                        }
                    }

                    // Save the index files and modlist again now that we've removed all the invalid entries.
                    foreach (var dkv in indexFiles)
                    {
                        await _index.SaveIndexFile(dkv.Value);
                    }
                    modding.SaveModList(modList);

                    // Show the user a message if we purged any real files.
                    if (toRemove.Any(x => !String.IsNullOrEmpty(x.fullPath) && !x.IsInternal()))
                    {
                        var text = String.Format(UIMessages.PatchDestroyedFiles, removedString);

                        FlexibleMessageBox.Show(_mainWindow.Win32Window, text, "Destroyed Files Notification", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
                    }
                }

                // Always create clean index backups after this process is completed.

                _mainWindow.LockProgress.Report("Disabling Mods...");
                await modding.ToggleAllMods(false);

                _mainWindow.LockProgress.Report("Creating Index Backups...");
                var           pc = new ProblemChecker(_gameDirectory);
                DirectoryInfo backupDir;
                try
                {
                    Directory.CreateDirectory(Settings.Default.Backup_Directory);
                    backupDir = new DirectoryInfo(Settings.Default.Backup_Directory);
                }
                catch
                {
                    throw new Exception("Unable to create index backups.\nThe Index Backup directory is invalid or inaccessible: " + Settings.Default.Backup_Directory);
                }

                await pc.BackupIndexFiles(backupDir);

                // Now restore the modlist enable/disable state back to how the user had it before.
                _mainWindow.LockProgress.Report("Re-Enabling mods...");

                // Re-enable things.
                await modding.ToggleMods(true, enabledMods.Select(x => x.fullPath));

                FlexibleMessageBox.Show(_mainWindow.Win32Window, UIMessages.PostPatchComplete, "Post-Patch Process Complete", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            }
            catch (Exception Ex)
            {
                // Show the user the error, then let them go about their business of fixing things.
                FlexibleMessageBox.Show(_mainWindow.Win32Window, String.Format(UIMessages.PostPatchError, Ex.Message), "Post-Patch Failure", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            }
            finally
            {
                if (resetLumina)
                {
                    // Reset lumina mode back to on if we disabled it to perform update checks.
                    XivCache.SetGameInfo(gi.GameDirectory, gi.GameLanguage, gi.DxMode, true, false, gi.LuminaDirectory, true);
                }

                XivCache.CacheWorkerEnabled = workerStatus;
                await _mainWindow.UnlockUi(this);
            }
        }
コード例 #9
0
        /// <summary>
        /// Event handler for the start over menu item clicked
        /// </summary>
        private async void Menu_StartOver_Click(object sender, RoutedEventArgs e)
        {
            var gameDirectory = new DirectoryInfo(Settings.Default.FFXIV_Directory);

            var index    = new Index(gameDirectory);
            var outdated = false;

            if (index.IsIndexLocked(XivDataFile._0A_Exd))
            {
                FlexibleMessageBox.Show(UIMessages.IndexLockedErrorMessage, UIMessages.IndexLockedErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            var result = FlexibleMessageBox.Show(UIMessages.StartOverMessage, UIMessages.StartOverTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Information);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                var indexBackupsDirectory = new DirectoryInfo(Settings.Default.Backup_Directory);

                if (!Directory.Exists(indexBackupsDirectory.FullName))
                {
                    FlexibleMessageBox.Show(UIMessages.BackupFolderAccessErrorMessage,
                                            UIMessages.IndexBackupsErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                var filesToCheck = new XivDataFile[] { XivDataFile._01_Bgcommon, XivDataFile._04_Chara, XivDataFile._06_Ui };

                var problemChecker = new ProblemChecker(gameDirectory);

                foreach (var xivDataFile in filesToCheck)
                {
                    var backupFile = new DirectoryInfo($"{indexBackupsDirectory.FullName}\\{xivDataFile.GetDataFileName()}.win32.index");

                    if (!File.Exists(backupFile.FullName))
                    {
                        continue;
                    }

                    var outdatedCheck = await problemChecker.CheckForOutdatedBackups(xivDataFile, indexBackupsDirectory);

                    if (!outdatedCheck)
                    {
                        FlexibleMessageBox.Show(UIMessages.OutdatedBackupsErrorMessage, UIMessages.IndexBackupsErrorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);

                        outdated = true;
                    }
                }

                await Task.Run(async() =>
                {
                    var modding = new Modding(gameDirectory);
                    await modding.DeleteAllFilesAddedByTexTools();

                    var dat = new Dat(gameDirectory);

                    var modListDirectory = new DirectoryInfo(Path.Combine(gameDirectory.Parent.Parent.FullName, XivStrings.ModlistFilePath));

                    var backupFiles = Directory.GetFiles(indexBackupsDirectory.FullName);

                    // Make sure backups exist
                    if (backupFiles.Length == 0)
                    {
                        FlexibleMessageBox.Show(string.Format(UIMessages.NoBackupsFoundErrorMessage, indexBackupsDirectory.FullName),
                                                UIMessages.BackupFilesMissingTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                        // Toggle off all mods
                        await modding.ToggleAllMods(false);
                    }
                    else if (outdated)
                    {
                        // Toggle off all mods
                        await modding.ToggleAllMods(false);
                    }
                    else
                    {
                        // Copy backups to ffxiv folder
                        foreach (var backupFile in backupFiles)
                        {
                            if (backupFile.Contains(".win32.index"))
                            {
                                File.Copy(backupFile, $"{gameDirectory}/{Path.GetFileName(backupFile)}", true);
                            }
                        }
                    }

                    // Delete modded dat files
                    foreach (var xivDataFile in (XivDataFile[])Enum.GetValues(typeof(XivDataFile)))
                    {
                        var datFiles = await dat.GetModdedDatList(xivDataFile);

                        foreach (var datFile in datFiles)
                        {
                            File.Delete(datFile);
                        }

                        if (datFiles.Count > 0)
                        {
                            await problemChecker.RepairIndexDatCounts(xivDataFile);
                        }
                    }

                    // Delete mod list
                    File.Delete(modListDirectory.FullName);

                    modding.CreateModlist();
                });

                UpdateViews(ItemTreeView.SelectedItem as Category);

                await this.ShowMessageAsync(UIMessages.StartOverCompleteTitle, UIMessages.StartOverCompleteMessage);
            }
        }
コード例 #10
0
        /// <summary>
        /// Event handler for the start over menu item clicked
        /// </summary>
        private async void Menu_StartOver_Click(object sender, RoutedEventArgs e)
        {
            var gameDirectory = new DirectoryInfo(Settings.Default.FFXIV_Directory);

            var index = new Index(gameDirectory);

            if (index.IsIndexLocked(XivDataFile._0A_Exd))
            {
                FlexibleMessageBox.Show("Error Accessing Index File\n\n" +
                                        "Please exit the game before proceeding.\n" +
                                        "-----------------------------------------------------\n\n",
                                        "Index Access Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            var result = FlexibleMessageBox.Show("Starting over will:\n\n" +
                                                 "Restore index files to their original state.\n" +
                                                 "Delete all mod dat files from game folder.\n" +
                                                 "Delete all mod list file entries.\n\n" +
                                                 "Do you want to start over?", "Start Over", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                var task = Task.Run((() =>
                {
                    var modding = new Modding(gameDirectory);
                    var dat = new Dat(gameDirectory);

                    var indexBackupsDirectory = new DirectoryInfo(Settings.Default.Backup_Directory);
                    var modListDirectory = new DirectoryInfo(Path.Combine(gameDirectory.Parent.Parent.FullName, XivStrings.ModlistFilePath));

                    var backupFiles = Directory.GetFiles(indexBackupsDirectory.FullName);

                    // Make sure backups exist
                    if (backupFiles.Length == 0)
                    {
                        FlexibleMessageBox.Show($"No backup files found in the following directory:\n{indexBackupsDirectory.FullName}\n\n" +
                                                $"Index entries will be put back to original offsets instead.\n" +
                                                "-----------------------------------------------------\n\n",
                                                "Backup Files Missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                        // Toggle off all mods
                        modding.ToggleAllMods(false);
                    }
                    else
                    {
                        // Copy backups to ffxiv folder
                        foreach (var backupFile in backupFiles)
                        {
                            if (backupFile.Contains(".win32.index"))
                            {
                                File.Copy(backupFile, $"{gameDirectory}/{Path.GetFileName(backupFile)}", true);
                            }
                        }
                    }

                    // Delete modded dat files
                    foreach (var xivDataFile in (XivDataFile[])Enum.GetValues(typeof(XivDataFile)))
                    {
                        var datFiles = dat.GetModdedDatList(xivDataFile);

                        foreach (var datFile in datFiles)
                        {
                            File.Delete(datFile);
                        }
                    }

                    // Delete mod list
                    File.Delete(modListDirectory.FullName);

                    modding.CreateModlist();
                }));

                task.Wait();

                await this.ShowMessageAsync("Start Over Complete", "The start over process has been completed.");
            }
        }