/// <summary> /// The main program had an error where componentdata from a previous voicepack was still present in a voicepack that does not /// use it. This function gets rid of that unused data. /// </summary> /// <returns>List of removed keys</returns> public static List <string> RemoveUnusedComponentData(VoicepackExtended voicepack) { var keysNotReferenced = new List <string>(); if (voicepack?.Voicepack?.componentData == null) { return(keysNotReferenced); } foreach (var item in voicepack.Voicepack.componentData) { if (!FindPAKreferenceInVoicepackAndReplace(voicepack, item.Key)) { keysNotReferenced.Add(item.Key); } } foreach (var keyNotReferenced in keysNotReferenced) { voicepack.Voicepack.componentData.Remove(keyNotReferenced); Debug.WriteLine($"ComponentData removed with key: {keyNotReferenced}"); } return(keysNotReferenced); }
/// <summary> /// This function prepares voicepacks for merging, they sometimes use the same key to identify a certain resource and /// use that key in a dictionary (which needs to be merged and cant contain duplicate keys). /// This function will find those keys and change them. /// </summary> /// <param name="lhs">left hand side, can be null</param> /// <param name="rhs">right hand side, can be null</param> public static List <string> ResolveComponentDataKeyClashes(VoicepackExtended lhs, VoicepackExtended rhs) { var clashingKeys = new List <string>(); if (lhs?.Voicepack?.componentData == null || rhs?.Voicepack?.componentData == null) { return(clashingKeys); } clashingKeys = FindComponentDataKeyClashes(lhs.Voicepack.componentData, rhs.Voicepack.componentData); if (!clashingKeys.Any()) { return(clashingKeys); } var lhsNewKeyPrefix = lhs.Voicepack.GetPAKFilePath() ?? lhs.Voicepack.GetFilePath() ?? Guid.NewGuid().ToString(); ChangeComponentDataKeys(lhs, clashingKeys, lhsNewKeyPrefix); var rhsNewKeyPrefix = rhs.Voicepack.GetPAKFilePath() ?? rhs.Voicepack.GetFilePath() ?? Guid.NewGuid().ToString(); ChangeComponentDataKeys(rhs, clashingKeys, rhsNewKeyPrefix); if (lhsNewKeyPrefix == rhsNewKeyPrefix) { throw new InvalidOperationException($"prefixes should differ, something went wrong, prefix = {lhsNewKeyPrefix}"); } return(clashingKeys); }
public static void Merge(VoicepackExtended voicepack, VoicepackExtended otherVoicepack) { VoicepackCleaner.RemoveUnusedComponentData(voicepack); VoicepackCleaner.RemoveUnusedComponentData(otherVoicepack); VoicepackCleaner.ResolveComponentDataKeyClashes(voicepack, otherVoicepack); MergeAchievementList(voicepack.Voicepack.groupManager.achievementList, otherVoicepack.Voicepack.groupManager.achievementList); MergeComponentData(voicepack.Voicepack.componentData, otherVoicepack.Voicepack.componentData); //TODO //VoicepackMerger.MergeComponentInformation(Voicepack.componentInformation, other.Voicepack.componentInformation); }
/// <summary> /// Merges the voicepack with filename into this (this can be empty) /// Returns true if it was able to load the voicepack from disk /// </summary> public bool Merge(string voicePackFilename) { var other = new VoicepackExtended(); if (other.LoadFromFile(voicePackFilename)) { this.Merge(other); return(true); } return(false); }
/// <summary> /// Will change all the oldKeys, by prepending the prefix, in the componentData of pack /// </summary> /// <remarks>presumes all the oldKeys are in the componentData of pack</remarks> public static void ChangeComponentDataKeys(VoicepackExtended pack, List <string> oldKeys, string prefix) { foreach (var oldKey in oldKeys) { var newKey = $"{prefix}:{oldKey}"; pack.Voicepack.componentData[newKey] = pack.Voicepack.componentData[oldKey]; pack.Voicepack.componentData.Remove(oldKey); FindPAKreferenceInVoicepackAndReplace(pack, oldKey, newKey); Debug.WriteLine($"ComponentData key changed, old key: {oldKey} -- new key: {newKey}"); } }
/// <summary> /// Merges the achievementsOptionsComponens (aka voicepack) of other into this /// </summary> /// <param name="other"></param> public void Merge(VoicepackExtended other) { if (!IsValidVoicepackLoaded()) { throw new InvalidOperationException(); } if (other == null || !other.IsValidVoicepackLoaded()) { throw new ArgumentNullException(); } VoicepackMerger.Merge(this, other); }
public bool EqualComponentInfo(VoicepackExtended other) { if (Voicepack?.componentInformation == null && other.Voicepack?.componentInformation == null) { return(true); } if (Voicepack?.componentInformation == null || other.Voicepack?.componentInformation == null) { return(false); } return(VoicepackComparer.EqualComponentInformation(Voicepack.componentInformation, other.Voicepack.componentInformation)); }
/// <summary> /// Finds the string that is used to reference componentData to the achievent or background image, and optionally changes it /// </summary> /// <remarks> /// Because of immutable strings, I don't see a way to create the find function separate from /// change function. As any reference to a string I try to return and change, would not change the original string. /// So can only work with a container of a string. /// To avoid code duplication of a search only function: if you only want to search, pass null as newPAKReference /// </remarks> /// <param name="voicepack">voicepack to search in</param> /// <param name="oldPAKReference">string to search for</param> /// <param name="newPAKReference">string to replace oldPAKReference with, pass null to search without changing</param> /// <returns>true if found (and optionally changed), false if not found</returns> public static bool FindPAKreferenceInVoicepackAndReplace(VoicepackExtended voicepack, string oldPAKReference, string newPAKReference = null) { var groupManager = voicepack.Voicepack.groupManager; //check backgroundimage if (groupManager.pakBackgroundImage == oldPAKReference) { if (newPAKReference != null) { groupManager.pakBackgroundImage = newPAKReference; } return(true); } //check achievements/sounds foreach (var achievementPair in groupManager.achievementList) { var achievement = achievementPair.Value; //check old style one sound achievement property if (achievement.pakSoundPath == oldPAKReference) { if (newPAKReference != null) { achievement.pakSoundPath = newPAKReference; } return(true); } //check new style dynamicsounds achievement property if (achievement.dynamicSounds?.sounds == null) { continue; } foreach (var sound in achievement.dynamicSounds.sounds) { if (sound.pakSoundFile == oldPAKReference) { if (newPAKReference != null) { sound.pakSoundFile = newPAKReference; } return(true); } } } //not found return(false); }
/// <summary> /// Checks if this.voicepack refers to the same sounds as other.voicepack /// </summary> /// <returns>true when equal, false when not equal</returns> public bool EqualSoundFilenames(VoicepackExtended other) { if (!this.IsValidVoicepackLoaded() && !other.IsValidVoicepackLoaded()) { return(true); } if (!this.IsValidVoicepackLoaded() || !other.IsValidVoicepackLoaded()) { return(false); } var achievements = Voicepack.groupManager.achievementList; var otherAchievements = other.Voicepack.groupManager.achievementList; return(VoicepackComparer.EqualAchievementLists(achievements, otherAchievements)); }
/// <summary> /// Saves this.Voicepack to a binary voicepack file. Makes sure any global state that might be altered during this /// operation is restored. /// </summary> /// <remarks> see remarks LoadFromFile() </remarks> public void ExportToFile(string filename) { if (!IsValidVoicepackLoaded()) { return; } var globalBackup = new VoicepackExtended(); globalBackup.GetFromGlobal(); { this.SetAsGlobal(); this.Voicepack.CreatePAKFile(filename); this.GetFromGlobal(); //make sure the global friends are copied } globalBackup.SetAsGlobal(); }
/// <summary> /// Loads the voicepack from file into this instance. Restores any global state that is altered during this operation. /// </summary> /// <remarks> /// the function achievementOptions.LoadFromPAKFile(string) will always load itself into the global instance, thats why we need /// the workaround in this function to load it in (move it in) a seperate instance. /// </remarks> public bool LoadFromFile(string filename) { var globalBackup = new VoicepackExtended(); globalBackup.GetFromGlobal(); { try { GlobalVariablesPS2.achievementOptions = new AchievementOptionsComponents(); GlobalVariablesPS2.achievementOptions.LoadFromPAKFile(filename); this.GetFromGlobal(); } catch (Exception e) { MessageBox.Show($"Failed to load:\n{filename}\n\n With error:\n{e}"); } } globalBackup.SetAsGlobal(); return(IsValidVoicepackLoaded()); }