public static void UpdateRecordCount(Plugin plugin) { int reccount = -1 + plugin.Records.Cast<Rec>().Sum(r => sanitizeCountRecords(r)); var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null) { if (tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8) { byte[] data = tes4.SubRecords[0].GetData(); byte[] reccountbytes = TypeConverter.si2h(reccount); for (int i = 0; i < 4; i++) data[4 + i] = reccountbytes[i]; tes4.SubRecords[0].SetData(data); } } }
public NewMediumLevelRecordEditor(Plugin p, Record r, SubRecord sr, SubrecordStructure ss) { InitializeComponent(); Icon = Resources.tesv_ico; SuspendLayout(); this.sr = sr; this.ss = ss; this.p = p; this.r = r; // walk each element in standard fashion int panelOffset = 0; try { foreach (var elem in ss.elements) { Control c = null; if (elem.options != null && elem.options.Length > 1) { c = new OptionsElement(); } else if (elem.flags != null && elem.flags.Length > 1) { c = new FlagsElement(); } else { switch (elem.type) { case ElementValueType.LString: c = new LStringElement(); break; case ElementValueType.FormID: c = new FormIDElement(); break; case ElementValueType.Blob: c = new HexElement(); break; default: c = new TextElement(); break; } } if (c is IElementControl) { var ec = c as IElementControl; ec.formIDLookup = p.GetRecordByID; ec.formIDScan = p.EnumerateRecords; ec.strIDLookup = p.LookupFormStrings; ec.Element = elem; if (elem.repeat > 0) { var ge = new RepeatingElement(); c = ge; c.Left = 8; c.Width = fpanel1.Width - 16; c.Top = panelOffset; c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right; ge.InnerControl = ec; ge.Element = elem; ec = ge; } else if (elem.optional) { var re = new OptionalElement(); c = re; c.Left = 8; c.Width = fpanel1.Width - 16; c.Top = panelOffset; c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right; re.InnerControl = ec; re.Element = elem; ec = re; c = re; } else { c.Left = 8; c.Width = fpanel1.Width - 16; c.Top = panelOffset; c.Anchor = c.Anchor | AnchorStyles.Left | AnchorStyles.Right; } c.MinimumSize = c.Size; controlMap.Add(elem, ec); fpanel1.Controls.Add(c); panelOffset = c.Bottom; } } foreach (Element elem in r.EnumerateElements(sr, true)) { var es = elem.Structure; IElementControl c; if (controlMap.TryGetValue(es, out c)) { if (c is IGroupedElementControl) { var gc = c as IGroupedElementControl; gc.Elements.Add(elem.Data); } else { c.Data = elem.Data; } } } } catch { strWarnOnSave = "The subrecord doesn't appear to conform to the expected structure.\nThe formatted information may be incorrect."; Error.SetError(bSave, strWarnOnSave); Error.SetIconAlignment(bSave, ErrorIconAlignment.MiddleLeft); AcceptButton = bCancel; // remove save as default button when exception occurs CancelButton = bCancel; UpdateDefaultButton(); } ResumeLayout(); }
/// <summary> /// BuildSkyrimDicInTargetLanguage_Click /// </summary> private void BuildSkyrimDictionnary_Click(object sender, EventArgs e) { //TESVSnip.Functions.StartCounter(); Cursor.Current = Cursors.WaitCursor; Update(); try { translatorHelperContent.ClearMemo(); CloseProject_Click(sender, new EventArgs()); Plugin p = new Plugin(); TESVSnip.Functions.StartCounter(); string filePath = Path.Combine(Program.gameDataDir, @"Strings\Skyrim_" + translatorHelperContent.GetSourceLanguage() + ".strings"); if (!File.Exists(filePath)) { MessageBox.Show("Can't find " + filePath, "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Error); TESVSnip.Functions.StopCounter(); return; } filePath = Path.Combine(Program.gameDataDir, @"Strings\Skyrim_" + translatorHelperContent.GetTargetLanguage() + ".strings"); if (!File.Exists(filePath)) { MessageBox.Show("Can't find " + filePath, "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Error); TESVSnip.Functions.StopCounter(); return; } Properties.Settings.Default.LocalizationName = translatorHelperContent.GetSourceLanguage(); p.ReloadStrings("Skyrim", Path.Combine(Program.gameDataDir, "Strings")); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", "CREATE"); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty); p.ReloadStrings("Update", Path.Combine(Program.gameDataDir, "Strings")); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty); //"WRITE"); Properties.Settings.Default.LocalizationName = translatorHelperContent.GetTargetLanguage(); p.ReloadStrings("Skyrim", Path.Combine(Program.gameDataDir, "Strings")); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty); //"CREATE"); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", String.Empty); p.ReloadStrings("Update", Path.Combine(Program.gameDataDir, "Strings")); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.Strings, "Strings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.DLStrings, "DLStrings", String.Empty); translatorHelperContent.GenerateSkyrimStringsDictionary(Properties.Settings.Default.LocalizationName, p.ILStrings, "ILStrings", "WRITE"); translatorHelperContent.AddToMemo("Load Strings in " + TESVSnip.Functions.StopCounter() + Environment.NewLine); TESVSnip.Functions.StartCounter(); PluginTree.UpdateRoots(); OpenPlugin(Path.Combine(Program.gameDataDir, "Skyrim.esm"), false); PluginTree.SelectedRecord = PluginTree.TopRecord; translatorHelperContent.PluginTree = GetPluginFromNode(PluginTree.SelectedRecord); translatorHelperContent.AddToMemo("Load Skyrim.esm in " + TESVSnip.Functions.StopCounter() + Environment.NewLine); TESVSnip.Functions.StartCounter(); translatorHelperContent.ProcessPlugIn(true, false, false, String.Empty); translatorHelperContent.AddToMemo("Parse Skyrim.esm in " + TESVSnip.Functions.StopCounter() + Environment.NewLine); translatorHelperContent.GenerateSkyrimStringsDictionaryWithSkyrimReference(); CloseAll(); } finally { Cursor.Current = Cursors.Default; CloseAll(); //translatorHelperContent.AddToMemo("Elapsed time:" + TESVSnip.Functions.StopCounter() + Environment.NewLine); } MessageBox.Show( "The " + translatorHelperContent.GetSourceLanguage() + " to " + translatorHelperContent.GetTargetLanguage() + " dictionary has been generated." + Environment.NewLine + "If STEAM updates STRINGS files, remember to regenerate dictionaries.", "Translator Helper", MessageBoxButtons.OK, MessageBoxIcon.Information); }
public static void SanitizePlugin(Plugin plugin) { // performance update to prevent lists from updating currently selected record bool oldHoldUpdates = BaseRecord.HoldUpdates; try { BaseRecord.HoldUpdates = true; if (plugin == null) throw new ApplicationException("Cannot select plugin"); var hdr = plugin.Records.OfType<Rec>().FirstOrDefault(x => x.Name == "TES4"); if (hdr == null) { throw new ApplicationException(Resources.PluginLacksAValidTes4RecordCannotContinue); } var toParse = new Queue<BaseRecord>(plugin.Records.OfType<BaseRecord>().Where(x => !x.Equals(hdr))); plugin.Clear(); plugin.AddRecord(hdr); var groups = new Dictionary<string, GroupRecord>(); foreach (string s in SanitizeOrder) { var gr = new GroupRecord(s); plugin.AddRecord(gr); groups[s] = gr; } bool looseGroupsWarning = false; bool unknownRecordsWarning = false; while (toParse.Count > 0) { var r = toParse.Dequeue(); if (r is GroupRecord) { var gr = (GroupRecord)r; if (gr.ContentsType == "CELL" || gr.ContentsType == "WRLD" || gr.ContentsType == "DIAL") { var gr2 = groups[gr.ContentsType]; foreach (BaseRecord r2 in gr.Records) gr2.AddRecord(r2); gr.Clear(); } else { foreach (BaseRecord r2 in gr.Records) toParse.Enqueue(r2); gr.Clear(); } } else if (r is Record) { var r2 = (Record)r; if (LooseGroups.Contains(r2.Name)) { looseGroupsWarning = true; plugin.AddRecord(r2); } else { if (groups.ContainsKey(r2.Name)) groups[r2.Name].AddRecord(r2); else { unknownRecordsWarning = true; plugin.AddRecord(r2); } } } } foreach (GroupRecord gr2 in groups.Values) { if (gr2.Records.Count == 0) plugin.DeleteRecord(gr2); } if (looseGroupsWarning) { MessageBox.Show(Resources.CannotSanitizeLooseGroups, Resources.WarningText); } if (unknownRecordsWarning) { MessageBox.Show(Resources.CannotSanitizeUnknownRecords, Resources.WarningText); } plugin.InvalidateCache(); UpdateRecordCount(plugin); /* int reccount = -1 + plugin.Records.Cast<Rec>().Sum(r => sanitizeCountRecords(r)); var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null) { if (tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8) { byte[] data = tes4.SubRecords[0].GetData(); byte[] reccountbytes = TypeConverter.si2h(reccount); for (int i = 0; i < 4; i++) data[4 + i] = reccountbytes[i]; tes4.SubRecords[0].SetData(data); } } */ } finally { BaseRecord.HoldUpdates = oldHoldUpdates; } }
internal static int InternalizeStrings(Plugin plugin) { bool anyModified = false; int count = 0; foreach (var record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (var sr in record.SubRecords) { var elements = record.EnumerateElements(sr, rawData: true).ToList(); foreach (var elem in elements) { if (elem.Structure != null && elem.Structure.type == ElementValueType.LString) { var data = elem.Data; uint id = TypeConverter.h2i(data); if (id == 0) continue; if (data.Count == 4) { var str = plugin.LookupFormStrings(id); if (!string.IsNullOrEmpty(str)) { elem.AssignValue<ArraySegment<byte>>(new ArraySegment<byte>(TypeConverter.str2h(str))); ++count; } } } } if (elements.Any(x => x.Changed)) { // need to repack the structure using (var ms = new MemoryStream(sr.GetReadonlyData().Length)) { foreach (var seg in elements.Select(elem => elem.Data)) ms.Write(seg.Array, seg.Offset, seg.Count); sr.SetData(ms.ToArray()); } anyModified = true; } } } if (anyModified) { var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null) tes4.Flags1 &= ~0x00000080U; } return count; }
internal static int CreateStringStubs(Plugin plugin) { if (plugin == null) return -1; var masters = plugin.Masters; if (masters == null || masters.Length == 0) return -1; int count = 0; foreach (var record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (var sr in record.SubRecords) { var elements = record.EnumerateElements(sr, rawData: true).ToList(); foreach (var elem in elements) { if (elem.Structure != null && elem.Structure.type == ElementValueType.LString) { var data = elem.Data; if (data.Count == 4) { string value; uint id = TypeConverter.h2i(data); if (id == 0) continue; if (!plugin.Strings.TryGetValue(id, out value)) { value = string.Format("STUB: {0} {1}", record.DescriptiveName, sr.DescriptiveName); plugin.Strings[id] = value; ++count; } } } } } } return count; }
internal static int CleanUnusedStrings(Plugin plugin) { if (plugin == null) return -1; var masters = plugin.Masters; if (masters == null || masters.Length == 0) return -1; LocalizedStringDict oldStrings = plugin.Strings; plugin.Strings = new LocalizedStringDict(); foreach (var record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (var sr in record.SubRecords) { var elements = record.EnumerateElements(sr, rawData: true).ToList(); foreach (var elem in elements) { if (elem.Structure != null && elem.Structure.type == ElementValueType.LString) { var data = elem.Data; if (data.Count == 4) { string value; uint id = TypeConverter.h2i(data); if (id == 0) continue; if (oldStrings.TryGetValue(id, out value)) { oldStrings.Remove(id); plugin.Strings[id] = value; } } } } } } return oldStrings.Count; }
/// <summary> /// Extract any internalized strings and put in string table /// </summary> /// <param name="plugin"></param> public static int ExtractInternalStrings(Plugin plugin) { int count = 0; // uint maxid = plugin.Masters.Max(x=>x.Strings.Count > 0 ? x.Strings.Keys.Max() : 0); // No need to check the masters string since the numbers are unique for every plugin bool anyModified = false; foreach (var record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (var sr in record.SubRecords) { var elements = record.EnumerateElements(sr, rawData: true).ToList(); foreach (var elem in elements) { if (elem.Structure != null && elem.Structure.type == ElementValueType.LString) { var data = elem.Data; uint id = TypeConverter.h2i(data); if (id == 0) continue; if (data.Count == 4 && TypeConverter.IsLikelyString(data)) { string str; if (plugin.Strings.TryGetValue(id, out str)) continue; } if (data.Count != 4 || TypeConverter.IsLikelyString(data)) { string value = TypeConverter.GetString(data); if (!String.IsNullOrEmpty(value)) { // uint nextid = Math.Max(maxid, plugin.Strings.Count == 0 ? 0 : plugin.Strings.Keys.Max()) + 1; // No need to check the masters strings since the numbers are unique for every plugin uint nextid = (plugin.Strings.Count == 0 ? 0 : plugin.Strings.Keys.Max()) + 1; int idx = plugin.Strings.FindValue(value); if (idx >= 0) { nextid = plugin.Strings.ElementAt(idx).Key; } else { plugin.Strings[nextid] = value; } elem.AssignValue<ArraySegment<byte>>( new ArraySegment<byte>((byte[])TypeConverter.i2h(nextid).Clone())); ++count; } } } } if (elements.Any(x => x.Changed)) { // need to repack the structure using (var ms = new MemoryStream(sr.GetReadonlyData().Length)) { foreach (var seg in elements.Select(elem => elem.Data)) ms.Write(seg.Array, seg.Offset, seg.Count); sr.SetData(ms.ToArray()); } anyModified = true; } } } if (anyModified) { var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null) tes4.Flags1 |= 0x00000080U; } return count; }
/// <summary> /// Copy any strings references from master not currently in current plugin /// </summary> /// <param name="plugin"></param> internal static int CopyMasterStringReferences(Plugin plugin) { if (plugin == null) return -1; var masters = plugin.Masters; if (masters == null || masters.Length == 0) return -1; int count = 0; foreach (var record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (var sr in record.SubRecords) { var elements = record.EnumerateElements(sr, rawData: true).ToList(); foreach (var elem in elements) { if (elem.Structure != null && elem.Structure.type == ElementValueType.LString) { var data = elem.Data; if (data.Count == 4) { string value; uint id = TypeConverter.h2i(data); if (id == 0) continue; if (!plugin.Strings.TryGetValue(id, out value)) { foreach (var master in masters.Reverse()) { if ( master.Strings.TryGetValue(id, out value) ) { ++count; plugin.Strings[id] = value; break; } } } } } } } } return count; }
public static void updateFormIDReference(Plugin plugin, uint oldFormID, uint newFormID, ref uint refCount) { foreach (Record record in plugin.Enumerate().OfType<Record>()) { record.MatchRecordStructureToRecord(); foreach (SubRecord sr in record.SubRecords) { var elements = sr.EnumerateElements(true).ToList(); foreach (Element e in elements) { if (e.Structure != null && e.Structure.type == ElementValueType.FormID) { if ((uint)e.Value == oldFormID) { e.AssignValue<uint>((object)newFormID); refCount++; } } } } } }
public static void updateFormIDReference(Plugin plugin, uint oldFormID, uint newFormID) { uint refCount = 0; updateFormIDReference(plugin, oldFormID, newFormID, ref refCount); }
public static uint getNextFormID(Plugin plugin) { var tes4 = plugin.Records.OfType<Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null && tes4.SubRecords.Count > 0 && tes4.SubRecords[0].Name == "HEDR" && tes4.SubRecords[0].Size >= 8) { byte[] data = tes4.SubRecords[0].GetData(); uint formid = (uint)TypeConverter.GetObject<uint>(data, 8); TypeConverter.i2h(formid + 1, data, 8); tes4.SubRecords[0].SetData(data); return formid; } throw new ApplicationException(Resources.PluginLacksAValidTes4RecordCannotContinue); }
public static void StripEDIDs(Plugin p) { foreach (Rec r in p.Records) StripEDIDsInternal(r); }
public static void Setup(Plugin[] plugins) { if (!Inited) Init(); TokenStream.Reset(); edidList.Clear(); globals.Clear(); farVars.Clear(); var records = new Dictionary<uint, Record>(); uint mask; var quests = new List<Pair<uint, Record>>(); var refs = new List<Pair<uint, Record>>(); var RefLookupTable = new Dictionary<uint, uint>(); for (uint i = 0; i < plugins.Length - 1; i++) { var plugin = plugins[i]; if (plugin == null) continue; if (plugin.Records.OfType<BaseRecord>().FirstOrDefault(x => x.Name == "TES4") == null) continue; mask = (uint) plugin.Masters.Count(); mask <<= 24; uint id = i << 24; foreach (Rec r in plugin.Records) RecursePlugin(r, mask, id, records, quests, refs); foreach (Pair<uint, Record> recs in refs) { if (RefLookupTable.ContainsKey(recs.Key) && RefLookupTable[recs.Key] != 0) quests.Add(new Pair<uint, Record>(RefLookupTable[recs.Key], recs.Value)); else if (records.ContainsKey(recs.Key)) { Record r = records[recs.Key]; uint formID = 0; foreach (SubRecord sr in r.SubRecords) { if (sr.Name == "SCRI") { byte[] bytes = sr.GetReadonlyData(); uint formid = (TypeConverter.h2i(bytes[0], bytes[1], bytes[2], bytes[3])); if ((formid & 0xff000000) == mask) { formID = (formid & 0xffffff) + id; break; } } } quests.Add(new Pair<uint, Record>(formID, recs.Value)); } } RefLookupTable.Clear(); } foreach (Rec r in plugins[plugins.Length - 1].Records) RecursePlugin(r, records, quests, refs); foreach (Pair<uint, Record> recs in refs) { if (RefLookupTable.ContainsKey(recs.Key) && RefLookupTable[recs.Key] != 0) quests.Add(new Pair<uint, Record>(RefLookupTable[recs.Key], recs.Value)); else if (records.ContainsKey(recs.Key)) { Record r = records[recs.Key]; uint formID = 0; foreach (SubRecord sr in r.SubRecords) { if (sr.Name == "SCRI") { byte[] bytes = sr.GetReadonlyData(); formID = (TypeConverter.h2i(bytes[0], bytes[1], bytes[2], bytes[3])); break; } } quests.Add(new Pair<uint, Record>(formID, recs.Value)); } } foreach (KeyValuePair<uint, Record> recs in records) { string edid = recs.Value.SubRecords[0].GetStrData().ToLowerInvariant(); if (recs.Value.Name == "GLOB") { TokenStream.AddGlobal(edid); globals[edid] = recs.Key; } else { TokenStream.AddEdid(edid); edidList[edid] = new Pair<uint, string>(recs.Key, recs.Value.Name); } } edidList["player"] = new Pair<uint, string>(0x14, "NPC_"); TokenStream.AddEdid("player"); edidList["playerref"] = new Pair<uint, string>(0x14, "NPC_"); TokenStream.AddEdid("playerref"); var vars = new Dictionary<string, ushort>(); foreach (Pair<uint, Record> quest in quests) { if (!records.ContainsKey(quest.Key)) continue; Record scpt = records[quest.Key]; string edid = quest.Value.SubRecords[0].GetStrData(); for (int i = 0; i < scpt.SubRecords.Count - 1; i++) { if (scpt.SubRecords[i].Name == "SLSD") { byte[] bytes = scpt.SubRecords[i].GetReadonlyData(); vars[scpt.SubRecords[i + 1].GetStrData().ToLowerInvariant()] = TypeConverter.h2s(bytes[0], bytes[1]); } } if (vars.Count > 0) { farVars[edid.ToLowerInvariant()] = vars; vars = new Dictionary<string, ushort>(); } } }