/// <summary> /// Edits the specified game specific value. /// </summary> /// <remarks> /// This method writes the given value in the specified game specific value, if it /// is owned by the mod being upgraded. If the specified edit is not owned by the /// mod being upgraded, the edit is archived in the install log. /// /// If the edit was not previously installed by the mod, then the normal install /// rules apply, including confirming overwrite if applicable. /// </remarks> /// <param name="p_strKey">The key of the edited Game Specific Value.</param> /// <param name="p_bteValue">The value to install.</param> /// <returns><c>true</c> if the value was set; <c>false</c> otherwise.</returns> public override bool EditGameSpecificValue(string p_strKey, byte[] p_bteValue) { IList <IMod> lstInstallers = InstallLog.GetGameSpecificValueEditInstallers(p_strKey); if (lstInstallers.Contains(Mod, ModComparer.Filename)) { if (!ModComparer.Filename.Equals(lstInstallers[lstInstallers.Count - 1], Mod)) { InstallLog.ReplaceGameSpecificValueEdit(Mod, p_strKey, p_bteValue); } else { ShaderEdit sedShader = new ShaderEdit(p_strKey); SDPArchives sdpManager = new SDPArchives(GameModeInfo, FileUtility); if (!TouchedFiles.Contains(sdpManager.GetPath(sedShader.Package))) { TouchedFiles.Add(sdpManager.GetPath(sedShader.Package)); TransactionalFileManager.Snapshot(sdpManager.GetPath(sedShader.Package)); } byte[] oldData; if (!sdpManager.EditShader(sedShader.Package, sedShader.ShaderName, p_bteValue, out oldData)) { throw new Exception("Failed to edit the shader"); } } OriginallyInstalledEdits.Remove(p_strKey); return(true); } return(base.EditGameSpecificValue(p_strKey, p_bteValue)); }
/// <summary> /// Edits the specified shader with the specified data. /// </summary> /// <param name="p_intPackage">The package containing the shader to edit.</param> /// <param name="p_strShaderName">The shader to edit.</param> /// <param name="p_bteData">The value to which to edit the shader.</param> /// <returns> /// <lang langref="true" /> if the value was set; <lang langref="false" /> /// if the user chose not to overwrite the existing value. /// </returns> /// <exception cref="ShaderException">Thrown if the shader could not be edited.</exception> public virtual bool EditShader(int p_intPackage, string p_strShaderName, byte[] p_bteData) { var strShaderKey = String.Format("sdp:{0}/{1}", p_intPackage, p_strShaderName); var strOldMod = InstallLog.Current.GetCurrentGameSpecifcValueEditorModName(strShaderKey); if (strOldMod != null) { var strMessage = String.Format("Shader '{0}' in package '{1}' has already been overwritten by '{2}'\n" + "Overwrite the changes?", p_strShaderName, p_intPackage, strOldMod); if ( System.Windows.Forms.MessageBox.Show(strMessage, "Confirm Overwrite", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { return(false); } } PermissionsManager.CurrentPermissions.Assert(); byte[] oldData; if (!SDPArchives.EditShader(p_intPackage, p_strShaderName, p_bteData, out oldData)) { throw new ShaderException("Failed to edit the shader"); } //if we are overwriting an original shader, back it up if ((strOldMod == null) || (oldData != null)) { Installer.MergeModule.BackupOriginalGameSpecificValueEdit(strShaderKey, oldData); } Installer.MergeModule.AddGameSpecificValueEdit(strShaderKey, p_bteData); return(true); }
/// <summary> /// Edits the specified game specific value. /// </summary> /// <param name="p_strKey">The key of the edited Game Specific Value.</param> /// <param name="p_bteValue">The value to install.</param> /// <returns><c>true</c> if the value was set; <c>false</c> otherwise.</returns> public virtual bool EditGameSpecificValue(string p_strKey, byte[] p_bteValue) { if (m_booDontOverwriteAll) { return(false); } ShaderEdit sedShader = new ShaderEdit(p_strKey); SDPArchives sdpManager = new SDPArchives(GameModeInfo, FileUtility); if (!TouchedFiles.Contains(sdpManager.GetPath(sedShader.Package))) { TouchedFiles.Add(sdpManager.GetPath(sedShader.Package)); TransactionalFileManager.Snapshot(sdpManager.GetPath(sedShader.Package)); } IMod modOldMod = InstallLog.GetCurrentGameSpecificValueEditOwner(p_strKey); if (!m_booOverwriteAll && (modOldMod != null)) { string strMessage = String.Format("Shader '{0}' in package '{1}' has already been overwritten by '{2}'\n" + "Overwrite the changes?", sedShader.ShaderName, sedShader.Package, modOldMod.ModName); switch (m_dlgOverwriteConfirmationDelegate(strMessage, false, false)) { case OverwriteResult.YesToAll: m_booOverwriteAll = true; break; case OverwriteResult.NoToAll: m_booDontOverwriteAll = true; break; case OverwriteResult.Yes: break; default: return(false); } } byte[] oldData; if (!sdpManager.EditShader(sedShader.Package, sedShader.ShaderName, p_bteValue, out oldData)) { throw new Exception("Failed to edit the shader"); } //if we are overwriting an original shader, back it up if ((modOldMod == null) && (oldData != null)) { InstallLog.LogOriginalGameSpecificValue(p_strKey, oldData); } InstallLog.AddGameSpecificValueEdit(Mod, p_strKey, p_bteValue); return(true); }
/// <summary> /// Upgrades the sdp edits log entries. /// </summary> /// <remarks> /// This analyses the mods and determines, as best as possible, who edited which shaders, and attempts /// to reconstruct the install order. The resulting information is then put in the new install log. /// </remarks> /// <param name="p_xmlModInstallLog">The current mod install log we are parsing to upgrade.</param> /// <param name="p_strModBaseName">The base name of the mod whose install log is being parsed.</param> private void UpgradeSdpEdits(XmlDocument p_xmlModInstallLog, string p_strModBaseName) { var xnlSdpEdits = p_xmlModInstallLog.SelectNodes("descendant::sdpEdits/*"); foreach (XmlNode xndSdpEdit in xnlSdpEdits) { var intPackage = Int32.Parse(xndSdpEdit.Attributes.GetNamedItem("package").Value); var strShader = xndSdpEdit.Attributes.GetNamedItem("shader").Value; var strShaderKey = String.Format("sdp:{0}/{1}", intPackage, strShader); var bteOldValue = GetOldSdpValue(intPackage, strShader); //we have no way of knowing who last edited the shader - that information // was not tracked // so, let's just do first come first serve if (!m_lstSeenShader.Contains(intPackage + "~" + strShader.ToLowerInvariant())) { //this is the first mod we have encountered that edited this shader, // so let's assume it is the lastest mod to have made the edit... InstallLog.Current.AddGameSpecificValueEdit(p_strModBaseName, strShaderKey, SDPArchives.GetShader(intPackage, strShader)); //...and backup the old value as the original value InstallLog.Current.PrependAfterOriginalGameSpecificValueEdit(InstallLog.ORIGINAL_VALUES, strShaderKey, bteOldValue); m_lstSeenShader.Add(intPackage + "~" + strShader.ToLowerInvariant()); } else { //someone else made the shader edit // we don't know what value was overwritten, so we will just use what we have // which is the old value InstallLog.Current.PrependAfterOriginalGameSpecificValueEdit(p_strModBaseName, strShaderKey, bteOldValue); } if (ProgressWorker.Cancelled()) { return; } ProgressWorker.StepItemProgress(); } }
/// <summary> /// Edits the specified shader with the specified data. /// </summary> /// <remarks> /// This method edits the specified shader, if the latest edit is owned /// by the fomod being upgraded. If the latest edit is not owned by the fomod /// being upgraded, the edit is simply archived in the appropriate location in the /// install log. /// If the edit was not previously installed by the fomod, then the normal install rules apply, /// including confirming overwrite if applicable. /// </remarks> /// <param name="p_intPackage">The package containing the shader to edit.</param> /// <param name="p_strShaderName">The shader to edit.</param> /// <param name="p_bteData">The value to which to edit the shader.</param> /// <returns> /// <lang langref="true" /> if the value was set; <lang langref="false" /> /// if the user chose not to overwrite the existing value. /// </returns> /// <exception cref="ShaderException">Thrown if the shader could not be edited.</exception> public override bool EditShader(int p_intPackage, string p_strShaderName, byte[] p_bteData) { PermissionsManager.CurrentPermissions.Assert(); var strShaderKey = String.Format("sdp:{0}/{1}", p_intPackage, p_strShaderName); IList <string> lstInstallers = InstallLog.Current.GetGameSpecifcValueInstallingMods(strShaderKey); if (lstInstallers.Contains(Fomod.BaseName)) { if (lstInstallers[lstInstallers.Count - 1].Equals(Fomod.BaseName)) { byte[] oldData; if (!SDPArchives.EditShader(p_intPackage, p_strShaderName, p_bteData, out oldData)) { throw new ShaderException("Failed to edit the shader"); } } Installer.MergeModule.AddGameSpecificValueEdit(strShaderKey, p_bteData); return(true); } return(base.EditShader(p_intPackage, p_strShaderName, p_bteData)); }
/// <summary> /// Undoes the edit made to the specified game specific value. /// </summary> /// <param name="p_strKey">The key of the edited Game Specific Value.</param> public void UnEditGameSpecificValue(string p_strKey) { ShaderEdit sedShader = new ShaderEdit(p_strKey); SDPArchives sdpManager = new SDPArchives(GameModeInfo, FileUtility); if (!TouchedFiles.Contains(sdpManager.GetPath(sedShader.Package))) { TouchedFiles.Add(sdpManager.GetPath(sedShader.Package)); TransactionalFileManager.Snapshot(sdpManager.GetPath(sedShader.Package)); } string strKey = InstallLog.GetModKey(Mod); string strCurrentOwnerKey = InstallLog.GetCurrentGameSpecificValueEditOwnerKey(p_strKey); //if we didn't edit the shader, then leave it alone if (!strKey.Equals(strCurrentOwnerKey)) { return; } //if we did edit the shader, replace it with the shader we overwrote // if we didn't overwrite the shader, then just delete it byte[] btePreviousData = InstallLog.GetPreviousGameSpecificValue(p_strKey); if (btePreviousData != null) { /*TODO (likely never): I'm not sure if this is the strictly correct way to unedit a shader * the original unedit code was: * * if (m_xelModInstallLogSdpEdits != null) * { * foreach (XmlNode node in m_xelModInstallLogSdpEdits.ChildNodes) * { * //TODO (likely never): Remove this workaround for the release version * if (node.Attributes.GetNamedItem("crc") == null) * { * InstallLog.UndoShaderEdit(int.Parse(node.Attributes.GetNamedItem("package").Value), node.Attributes.GetNamedItem("shader").Value, 0); * } * else * { * InstallLog.UndoShaderEdit(int.Parse(node.Attributes.GetNamedItem("package").Value), node.Attributes.GetNamedItem("shader").Value, * uint.Parse(node.Attributes.GetNamedItem("crc").Value)); * } * } * } * * where InstallLog.UndoShaderEdit was: * * public void UndoShaderEdit(int package, string shader, uint crc) * { * XmlNode node = sdpEditsNode.SelectSingleNode("sdp[@package='" + package + "' and @shader='" + shader + "']"); * if (node == null) return; * byte[] b = new byte[node.InnerText.Length / 2]; * for (int i = 0; i < b.Length; i++) * { * b[i] = byte.Parse("" + node.InnerText[i * 2] + node.InnerText[i * 2 + 1], System.Globalization.NumberStyles.AllowHexSpecifier); * } * if (SDPArchives.RestoreShader(package, shader, b, crc)) sdpEditsNode.RemoveChild(node); * } * * after looking at SDPArchives it is not clear to me why a crc was being used. * if ever it becomes evident that a crc is required, I will have to alter the log to store * a crc and pass it to the RestoreShader method. */ if (!sdpManager.RestoreShader(sedShader.Package, sedShader.ShaderName, btePreviousData, 0)) { throw new Exception("Failed to unedit the shader"); } } //TODO (likely never): how do we delete a shader? Right now, if there was no previous shader the current shader // remains }
/// <summary> /// Undoes the edit made to the specified shader. /// </summary> /// <param name="p_intPackage">The package containing the shader to edit.</param> /// <param name="p_strShaderName">The shader to edit.</param> /// <exception cref="ShaderException">Thrown if the shader could not be unedited.</exception> protected void UneditShader(int p_intPackage, string p_strShaderName) { var strShaderKey = String.Format("sdp:{0}/{1}", p_intPackage, p_strShaderName); var strKey = InstallLog.Current.GetModKey(Fomod.BaseName); var strCurrentOwnerKey = InstallLog.Current.GetCurrentGameSpecifcValueEditorModKey(strShaderKey); //if we didn't edit the shader, then leave it alone if (!strKey.Equals(strCurrentOwnerKey)) { return; } //if we did edit the shader, replace it with the shader we overwrote // if we didn't overwrite the shader, then just delete it var btePreviousData = InstallLog.Current.GetPreviousGameSpecifcValueData(strShaderKey); if (btePreviousData != null) { /*TODO: I'm not sure if this is the strictly correct way to unedit a shader * the original unedit code was: * * if (m_xelModInstallLogSdpEdits != null) * { * foreach (XmlNode node in m_xelModInstallLogSdpEdits.ChildNodes) * { * //TODO: Remove this workaround for the release version * if (node.Attributes.GetNamedItem("crc") == null) * { * InstallLog.UndoShaderEdit(int.Parse(node.Attributes.GetNamedItem("package").Value), node.Attributes.GetNamedItem("shader").Value, 0); * } * else * { * InstallLog.UndoShaderEdit(int.Parse(node.Attributes.GetNamedItem("package").Value), node.Attributes.GetNamedItem("shader").Value, * uint.Parse(node.Attributes.GetNamedItem("crc").Value)); * } * } * } * * where InstallLog.UndoShaderEdit was: * * public void UndoShaderEdit(int package, string shader, uint crc) * { * XmlNode node = sdpEditsNode.SelectSingleNode("sdp[@package='" + package + "' and @shader='" + shader + "']"); * if (node == null) return; * byte[] b = new byte[node.InnerText.Length / 2]; * for (int i = 0; i < b.Length; i++) * { * b[i] = byte.Parse("" + node.InnerText[i * 2] + node.InnerText[i * 2 + 1], System.Globalization.NumberStyles.AllowHexSpecifier); * } * if (SDPArchives.RestoreShader(package, shader, b, crc)) sdpEditsNode.RemoveChild(node); * } * * after looking at SDPArchives it is not clear to me why a crc was being used. * if ever it becomes evident that a crc is required, I will have to alter the log to store * a crc and pass it to the RestoreShader method. */ PermissionsManager.CurrentPermissions.Assert(); if (!SDPArchives.RestoreShader(p_intPackage, p_strShaderName, btePreviousData, 0)) { throw new ShaderException("Failed to unedit the shader"); } } //TODO: how do we delete a shader? Right now, if there was no previous shader the current shader // remains }