private static PatchResult ExecuteModsInternal(string gamedir, FileStorage storage, List <FileMod> mods, ProgressReporter progress, bool revert) { int total = mods.Count; int success = 0; for (int i = 0; i < mods.Count; i++) { FileMod mod = mods[i]; progress.Message(string.Format("{0}: {1}...", revert ? "Restoring" : "Patching", mod.GetDescription()), i, total); var results = mod.TryApply(storage); if (results == null) { progress.Error(string.Format("Failed to generate data: {0}", mod.GetDescription())); continue; } bool diskWriteSuccess = true; foreach (FileModResult result in results) { string path = Path.Combine(gamedir, result.TargetPath); if (result.ResultData != null) { if (!SenUtils.TryWriteFileIfDifferent(result.ResultData, path)) { progress.Error(string.Format("Failed to write to disk: {0}", path)); diskWriteSuccess = false; } } else { if (!SenUtils.TryDeleteFile(path)) { progress.Error(string.Format("Failed to delete from disk: {0}", path)); diskWriteSuccess = false; } } } if (diskWriteSuccess) { ++success; } } progress.Message(string.Format("Finished {0}.", revert ? "restoring files" : "applying patches"), total, total); return(new PatchResult(total, success)); }
private void ProcessSync(ProgressReporter progress) { foreach (var configuration in ResolveConfigurations()) { using (new LoggingContext(progress, configuration)) { try { progress.ReportSimple("Control Panel Sync: Processing Unicorn configuration " + configuration.Name, MessageLevel.Info); var pathResolver = configuration.Resolve <PredicateRootPathResolver>(); var retryer = configuration.Resolve <IDeserializeFailureRetryer>(); var consistencyChecker = configuration.Resolve <IConsistencyChecker>(); var loader = configuration.Resolve <SerializationLoader>(); var roots = pathResolver.GetRootSerializedItems(); int index = 1; loader.LoadAll(roots, retryer, consistencyChecker, item => { progress.ReportProgress((int)((index / (double)roots.Length) * 100)); index++; }); progress.ReportSimple("Control Panel Sync: Completed syncing Unicorn configuration " + configuration.Name, MessageLevel.Info); } catch (Exception ex) { progress.Error(ex); break; } } } }
public static FileStorage.InitReturnValue InitializeAndPersistFileStorage(string baseDir, KnownFile[] knownFiles, ProgressReporter progress) { if (!Directory.Exists(baseDir)) { progress.Error(string.Format("No directory found at {0}.", baseDir)); return(null); } string backupArchivePath = Path.Combine(baseDir, "senpatcher_rerun_revert_data.bin"); FileStorage.InitReturnValue fileStoreReturnValue = null; using (HyoutaUtils.HyoutaArchive.HyoutaArchiveContainer backupArchive = TryLoadBackupArchive(backupArchivePath, progress)) { progress.Message("Reading and identifying game files..."); fileStoreReturnValue = FileStorage.InitializeFromKnownFiles(baseDir, knownFiles, backupArchive); } foreach (var perFileErrors in fileStoreReturnValue.Errors) { foreach (var errorMessage in perFileErrors.errors) { progress.Error(errorMessage); break; // only show first error to the user, this is really confusing otherwise } } if (fileStoreReturnValue.ShouldWriteBackupArchive) { progress.Message(string.Format("Writing backup archive to {0}...", backupArchivePath)); Stream ms = new MemoryStream(); fileStoreReturnValue.Storage.WriteToHyoutaArchive(ms); using (var fs = new FileStream(backupArchivePath, FileMode.Create)) { ms.Position = 0; HyoutaUtils.StreamUtils.CopyStream(ms, fs); } } return(fileStoreReturnValue); }
private static HyoutaUtils.HyoutaArchive.HyoutaArchiveContainer TryLoadBackupArchive(string backupArchivePath, ProgressReporter progress) { try { if (File.Exists(backupArchivePath)) { progress.Message(string.Format("Loading backup archive at {0}...", backupArchivePath)); using (var fs = new HyoutaUtils.Streams.DuplicatableFileStream(backupArchivePath)) { return(new HyoutaUtils.HyoutaArchive.HyoutaArchiveContainer(fs)); } } } catch (Exception ex) { progress.Error(string.Format("Failed to load backup file archive: {0}", ex.Message)); } return(null); }
public void Run() { if (Progress == null) { Progress = new DummyProgressReporter(); } try { Result = FileModExec.ExecuteMods(Path, Storage, Mods, Progress); } catch (Exception ex) { Progress.Error("Error while patching game files: " + ex.Message); Progress.Finish(false); return; } Progress.Message("Successfully patched game files."); Progress.Finish(true); }
public void Cs1GameInit() { int CurrentProgress = 0; int TotalProgress = 4; bool shouldAutoCloseWindow = true; try { Progress.Message("Checking Sen1Launcher.exe...", CurrentProgress++, TotalProgress); using (var fs = new HyoutaUtils.Streams.DuplicatableFileStream(Sen1LauncherPath)) { SHA1 hash = ChecksumUtils.CalculateSHA1ForEntireStream(fs); if (hash != new SHA1(0x8dde2b39f128179aul, 0x0beb3301cfd56a98ul, 0xc0f98a55u)) { Progress.Error("Selected file does not appear to be Sen1Launcher.exe of version 1.6."); Progress.Finish(false); return; } } } catch (Exception ex) { Progress.Error("Error while validating Sen1Launcher.exe: " + ex.Message); Progress.Finish(false); return; } try { Path = System.IO.Path.GetDirectoryName(Sen1LauncherPath); Progress.Message("Checking if we have encoding errors in filenames...", CurrentProgress++, TotalProgress); if (FilenameFix.FixupIncorrectEncodingInFilenames(Path, 1, false, Progress)) { if (!FilenameFix.FixupIncorrectEncodingInFilenames(Path, 1, true, Progress)) { Progress.Error("Failed to fix encoding errors in filenames, attempting to proceed anyway..."); shouldAutoCloseWindow = false; } } Progress.Message("Initializing patch data...", CurrentProgress++, TotalProgress); var files = Sen1KnownFiles.Files; Progress.Message("Initializing game data...", CurrentProgress++, TotalProgress); var storageInit = FileModExec.InitializeAndPersistFileStorage(Path, files, Progress); Storage = storageInit?.Storage; if (storageInit == null || storageInit.Errors.Count != 0) { shouldAutoCloseWindow = false; } } catch (Exception ex) { Progress.Error("Error while initializing CS1 patch/game data: " + ex.Message); Progress.Finish(false); return; } ShouldProceedToPatchOptionWindow = Path != null && Storage != null; if (shouldAutoCloseWindow) { Progress.Message("Initialized CS1 data, proceeding to patch options...", CurrentProgress, TotalProgress); } else { Progress.Message("", CurrentProgress, TotalProgress); if (ShouldProceedToPatchOptionWindow) { Progress.Error( "Encountered problems while initializing CS1 data. " + "Closing this window will proceed to the patch options anyway, but be aware that some patches may not work correctly. " + "It is recommended to verify the game files using Steam or GOG Galaxy's build-in feature to do so, or to reinstall the game. " + "Please also ensure you're trying to patch a compatible version of the game. (XSEED release version 1.6; other game versions are not compatible)" ); } else { Progress.Error( "Unrecoverable issues while initializing CS1 data. " + "Please ensure SenPatcher has read and write access to the selected game directory, then try again." ); } } Progress.Finish(shouldAutoCloseWindow); }