public static bool HasEditCollision(GameModification currentMod, string file, IWriteContent content, FileWriterUtility fileWriter, List <FileModification> modifications, out ModCollision collision) { var actions = new ActionCollection(file, currentMod.Config.ModID, modifications); if (actions.moveAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Edit, FileModificationType.Moved, actions.moveAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.replaceAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Edit, FileModificationType.Replaced, actions.replaceAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.editAction != null && !fileWriter.CanWrite(file, content)) { return(AddModCollision(currentMod, ModInstallActionEnum.Edit, FileModificationType.Edited, actions.editAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.deleteAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Edit, FileModificationType.Deleted, actions.deleteAction.ModID, ModCollisionSeverity.Clash, out collision)); } collision = null; return(false); }
private void MoveFile_Internal(string targetPath, string destinationPath, GameModification mod) { if (IsReservedFile(targetPath)) { modifications.Add(new MoveFileModification(targetPath, destinationPath, true, mod.Config.ModID)); BackupFile(targetPath); } else { modifications.Add(new MoveFileModification(targetPath, destinationPath, false, mod.Config.ModID)); } if (IsReservedFile(destinationPath)) { modifications.Add(new ReplaceFileModification(destinationPath, true, mod.Config.ModID)); BackupFile(destinationPath); } else { modifications.Add(new AddFileModification(destinationPath, false, mod.Config.ModID)); } Directory.CreateDirectory(new FileInfo(destinationPath).DirectoryName); File.Move(targetPath, destinationPath, true); }
public void CheckFileWriteWithMove() { var actions = new List <FileModification>() { new MoveFileModification(exampleFile1, exampleDestination1, false, "Test.Move") }; var fileWriter = new FileWriterUtility(); var content = new WriteToFileAction.WriteContent() { Text = "Test", StartOffset = 12 }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Edit" } }; bool hasCollision = ModCollisionTracker.HasEditCollision(mod, exampleFile1, content, fileWriter, actions, out var collision); Assert.AreEqual(true, hasCollision); Assert.AreEqual(collision.severity, ModCollisionSeverity.Clash); Assert.AreEqual(collision.modID, "Test.Move"); Assert.IsTrue(collision.description.Contains("Attempting to write to a file that has been moved by another mod"), $"Actual: {collision.description}"); }
private static bool AddModCollision(GameModification mod, ModInstallActionEnum action, FileModificationType collisionReason, string collidingModID, ModCollisionSeverity severity, out ModCollision collision, string suffix = "") { string collisionReasonDescription = GetCollisionDescription(collisionReason); string actionDescription = GetModificationDescription(action); return(AddModCollision(mod, actionDescription, collisionReasonDescription, collidingModID, severity, out collision, suffix: suffix)); }
public static bool HasReplaceCollision(GameModification currentMod, string file, string replacementFile, List <FileModification> modifications, out ModCollision collision) { var actions = new ActionCollection(file, currentMod.Config.ModID, modifications); if (actions.moveAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Replace, FileModificationType.Moved, actions.moveAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.replaceAction != null && MD5Utility.CalculateMD5Hash(file) != MD5Utility.CalculateMD5Hash(replacementFile)) { return(AddModCollision(currentMod, ModInstallActionEnum.Replace, FileModificationType.Replaced, actions.replaceAction.ModID, ModCollisionSeverity.Clash, out collision, suffix: "(with different data)")); } if (actions.editAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Replace, FileModificationType.Edited, actions.editAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.deleteAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Replace, FileModificationType.Deleted, actions.deleteAction.ModID, ModCollisionSeverity.Clash, out collision)); } collision = null; return(false); }
public GameChangedEventArgs(AvailableGame game, GameModification gameModification) { Game = game ?? throw new ArgumentNullException(nameof(game)); if (gameModification == GameModification.Undefined) { throw new ArgumentOutOfRangeException(nameof(gameModification)); } GameModification = gameModification; }
public void AddActions(GameModification mod, ModInstallAction[] actions) { extractActions.AddRange(actions.Where(a => a.Action.SafeEquals("QuickBMSExtract", ignoreCase: true)).Select(a => new ModAction <QuickBMSExtractAction>(mod, a as QuickBMSExtractAction))); decompileActions.AddRange(actions.Where(a => a.Action.SafeEquals("UnluacDecompile", ignoreCase: true)).Select(a => new ModAction <UnluacDecompileAction>(mod, a as UnluacDecompileAction))); fileMoveActions.AddRange(actions.Where(a => a.Action.SafeEquals("MoveFile", ignoreCase: true)).Select(a => new ModAction <MoveFileAction>(mod, a as MoveFileAction))); bulkFileMoveActions.AddRange(actions.Where(a => a.Action.SafeEquals("MoveFiles", ignoreCase: true)).Select(a => new ModAction <MoveFilesAction>(mod, a as MoveFilesAction))); fileDeleteActions.AddRange(actions.Where(a => a.Action.SafeEquals("DeleteFiles", ignoreCase: true)).Select(a => new ModAction <DeleteFilesAction>(mod, a as DeleteFilesAction))); fileWriteActions.AddRange(actions.Where(a => a.Action.SafeEquals("WriteToFile", ignoreCase: true)).Select(a => new ModAction <WriteToFileAction>(mod, a as WriteToFileAction))); fileReplaceActions.AddRange(actions.Where(a => a.Action.SafeEquals("ReplaceFile", ignoreCase: true)).Select(a => new ModAction <ReplaceFileAction>(mod, a as ReplaceFileAction))); bulkFileReplaceActions.AddRange(actions.Where(a => a.Action.SafeEquals("ReplaceFiles", ignoreCase: true)).Select(a => new ModAction <ReplaceFilesAction>(mod, a as ReplaceFilesAction))); fileCopyActions.AddRange(actions.Where(a => a.Action.SafeEquals("CopyFile", ignoreCase: true)).Select(a => new ModAction <CopyFileAction>(mod, a as CopyFileAction))); bulkFileCopyActions.AddRange(actions.Where(a => a.Action.SafeEquals("CopyFiles", ignoreCase: true)).Select(a => new ModAction <CopyFilesAction>(mod, a as CopyFilesAction))); }
private void DeleteFile_Internal(string targetPath, GameModification mod) { if (IsReservedFile(targetPath)) { modifications.Add(new DeleteFileModification(targetPath, true, mod.Config.ModID)); BackupFile(targetPath); } else { modifications.Add(new DeleteFileModification(targetPath, false, mod.Config.ModID)); } File.Delete(targetPath); }
public ModActionCollection CreateFilteredCollection(GameModification mod, bool filterOut = false) { return(new ModActionCollection() { extractActions = extractActions.Where(a => Filter(a, mod, filterOut)).ToList(), decompileActions = decompileActions.Where(a => Filter(a, mod, filterOut)).ToList(), fileMoveActions = fileMoveActions.Where(a => Filter(a, mod, filterOut)).ToList(), bulkFileMoveActions = bulkFileMoveActions.Where(a => Filter(a, mod, filterOut)).ToList(), fileDeleteActions = fileDeleteActions.Where(a => Filter(a, mod, filterOut)).ToList(), fileWriteActions = fileWriteActions.Where(a => Filter(a, mod, filterOut)).ToList(), fileReplaceActions = fileReplaceActions.Where(a => Filter(a, mod, filterOut)).ToList(), bulkFileReplaceActions = bulkFileReplaceActions.Where(a => Filter(a, mod, filterOut)).ToList(), fileCopyActions = fileCopyActions.Where(a => Filter(a, mod, filterOut)).ToList() }); }
public void CheckFileMoveWithMove_SameTarget() { var actions = new List <FileModification>() { new MoveFileModification(exampleFile1, exampleDestination1, false, "Test.Move") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Move2" } }; bool hasCollision = ModCollisionTracker.HasMoveCollision(mod, exampleFile1, exampleDestination1, actions, out var collision); Assert.AreEqual(false, hasCollision); }
public void CheckFileReplaceWithReplace_SameData() { var actions = new List <FileModification>() { new ReplaceFileModification(exampleDestination1, false, "Test.Replace1") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Replace2" } }; bool hasCollision = ModCollisionTracker.HasReplaceCollision(mod, exampleFile1, exampleDestination3_exampleDestination1, actions, out var collision); Assert.AreEqual(false, hasCollision); }
public void CheckFileMoveWithAdd_DiffDest() { var actions = new List <FileModification>() { new AddFileModification(exampleFile2, false, "Test.Add") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Move" } }; bool hasCollision = ModCollisionTracker.HasMoveCollision(mod, exampleFile3, exampleFile1, actions, out var collision); Assert.AreEqual(false, hasCollision); }
public static string ResolvePath(string path, GameModification mod, Configuration config) { if (string.IsNullOrEmpty(path)) { return(null); } if (path.StartsWith("[GAME]", StringComparison.InvariantCultureIgnoreCase)) { return(ResolveGamePath(path, config)); } if (path.StartsWith("[MOD]", StringComparison.InvariantCultureIgnoreCase)) { return(ResolveModPath(path, mod)); } throw new Exception("Supplied path must begin with the following: [GAME], [MOD]"); }
public void CheckFileReplaceWithReplace_DifferentData() { var actions = new List <FileModification>() { new ReplaceFileModification(exampleFile1, false, "Test.Replace1") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Replace2" } }; bool hasCollision = ModCollisionTracker.HasReplaceCollision(mod, exampleFile1, testFile2, actions, out var collision); Assert.AreEqual(true, hasCollision); Assert.AreEqual(collision.severity, ModCollisionSeverity.Clash); Assert.AreEqual(collision.modID, "Test.Replace1"); Assert.IsTrue(collision.description.Contains("Attempting to replace a file that has been replaced by another mod (with different data)"), $"Actual: {collision.description}"); }
public void CheckFileReplaceWithMove() { var actions = new List <FileModification>() { new MoveFileModification(exampleFile1, "C:\\Example\\ExampleFile.txt", false, "Test.Move") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Replace" } }; bool hasCollision = ModCollisionTracker.HasReplaceCollision(mod, exampleFile1, exampleFile2, actions, out var collision); Assert.AreEqual(true, hasCollision); Assert.AreEqual(collision.severity, ModCollisionSeverity.Clash); Assert.AreEqual(collision.modID, "Test.Move"); Assert.IsTrue(collision.description.Contains("Attempting to replace a file that has been moved by another mod"), $"Actual: {collision.description}"); }
public void CheckFileMoveWithAdd_SameDest() { var actions = new List <FileModification>() { new AddFileModification(exampleFile1, false, "Test.Add") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Move" } }; bool hasCollision = ModCollisionTracker.HasMoveCollision(mod, exampleFile2, exampleFile1, actions, out var collision); Assert.AreEqual(true, hasCollision); Assert.AreEqual(collision.severity, ModCollisionSeverity.Clash); Assert.AreEqual(collision.modID, "Test.Add"); Assert.IsTrue(collision.description.Contains("Attempting to move a file to a destination that has been modified by another mod (with different data)"), $"Actual: {collision.description}"); }
public void CheckFileMoveWithWrite() { var actions = new List <FileModification>() { new EditFileModification(exampleFile1, false, "Test.Edit") }; var mod = new GameModification() { Config = new Data.BaseModConfiguration() { ModID = "Test.Move2" } }; bool hasCollision = ModCollisionTracker.HasMoveCollision(mod, exampleFile1, exampleDestination1, actions, out var collision); Assert.AreEqual(true, hasCollision); Assert.AreEqual(collision.severity, ModCollisionSeverity.Clash); Assert.AreEqual(collision.modID, "Test.Edit"); Assert.IsTrue(collision.description.Contains("Attempting to move a file that has been written to by another mod"), $"Actual: {collision.description}"); }
public static bool HasCopyCollision(GameModification currentMod, string file, string destinationPath, List <FileModification> modifications, out ModCollision collision) { var actions = new ActionCollection(file, currentMod.Config.ModID, modifications); var destinationActions = new ActionCollection(destinationPath, currentMod.Config.ModID, modifications); if (actions.moveAction != null && destinationPath != (actions.moveAction as MoveFileModification).DestinationPath) { return(AddModCollision(currentMod, ModInstallActionEnum.Copy, FileModificationType.Moved, actions.moveAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.replaceAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Copy, FileModificationType.Replaced, actions.replaceAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.editAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Copy, FileModificationType.Edited, actions.editAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (actions.deleteAction != null) { return(AddModCollision(currentMod, ModInstallActionEnum.Copy, FileModificationType.Deleted, actions.deleteAction.ModID, ModCollisionSeverity.Clash, out collision)); } if (destinationActions.lastAction != null && !(new[] { FileModificationType.Moved, FileModificationType.Deleted }).Contains(destinationActions.lastAction.Type)) { if (MD5Utility.CalculateMD5Hash(file) != MD5Utility.CalculateMD5Hash(destinationPath)) { string modPrefix = $"Mod collision detected while installing mod ({currentMod.Config.ModID})"; collision = new ModCollision(currentMod.Config.ModID, ModCollisionSeverity.Clash, $"{modPrefix}: Attempting to copy a file to a destination that has been modified by another mod (with different data) (conflicting mod: {destinationActions.lastAction.ModID})"); return(true); } } collision = null; return(false); }
private InstallationStatus ReplaceFile(string replacementFile, string targetFile, GameModification mod) { if (ModCollisionTracker.HasReplaceCollision(mod, targetFile, replacementFile, modifications, out var collision)) { return(HandleCollision(collision)); } if (!File.Exists(targetFile)) { throw new Exception($"Unable to find target path: {targetFile}"); } CopyFile_Internal(replacementFile, targetFile, mod); return(InstallationStatus.Success); }
public void AddActionsFromMod(GameModification mod) { var installActions = (mod.Config.InstallActions ?? new ModInstallAction[] { }); AddActions(mod, installActions); }
public ModAction(GameModification mod, T action) { this.mod = mod; this.action = action; }
public static string ResolveModPath(string path, GameModification mod) { return(Path.Combine(mod.Config.ModCachePath, path.Substring(5, path.Length - 5).TrimStart('\\').TrimStart('/'))); }
private InstallationStatus MoveFile(string targetFile, string destinationPath, GameModification mod) { // Have we already moved this file to the exact same destination? if (HasMovedFileToSameDestination(targetFile, destinationPath)) { return(InstallationStatus.Success); } if (ModCollisionTracker.HasMoveCollision(mod, targetFile, destinationPath, modifications, out var collision)) { return(HandleCollision(collision)); } if (!File.Exists(targetFile)) { throw new Exception($"Unable to find target path: {targetFile}"); } MoveFile_Internal(targetFile, destinationPath, mod); return(InstallationStatus.Success); }
private static bool AddModCollision(GameModification mod, string actionDescription, string collisionReasonDescription, string collidingModID, ModCollisionSeverity severity, out ModCollision collision, string suffix = "") { string modPrefix = $"Mod collision detected while installing mod ({mod.Config.ModID})"; collision = new ModCollision(collidingModID, severity, $"{modPrefix}: Attempting to {actionDescription} that has been {collisionReasonDescription} another mod{(string.IsNullOrEmpty(suffix) ? "" : $" {suffix}")} (conflicting mod: {collidingModID})");
private bool Filter <TAction>(ModAction <TAction> action, GameModification mod, bool filterOut = false) { return(filterOut ? !action.mod.Equals(mod) : action.mod.Equals(mod)); }
private InstallationStatus CopyFile(string targetFile, string destinationPath, GameModification mod) { if (ModCollisionTracker.HasCopyCollision(mod, targetFile, destinationPath, modifications, out var collision)) { return(HandleCollision(collision)); } if (!File.Exists(targetFile)) { throw new Exception($"Unable to find target path: {targetFile}"); } // Copying files occurs near the start, and should not cause conflicts CopyFile_Internal(targetFile, destinationPath, mod); return(InstallationStatus.Success); }