/// <summary>Get the item language archive, which contains the <see cref="ItemArchiveId"/> <see cref="StringArchive"/>s.</summary> /// <param name="baseArchive"></param> /// <param name="language"></param> /// <returns></returns> public static Archive GetItemLanguageArchive(Archive baseArchive, Language language = Language.English) { string path = string.Format(LanguageItemArchivePath, GetLanguageId(language)); ArchiveRecord record = baseArchive.FindRecordByPath(path); if (record == null) { return(null); } Asset contents = record.Contents; return(contents as Archive); }
/// <summary>Get the string archive from the <see cref="ItemArchiveId"/>.</summary> /// <param name="baseArchive"></param> /// <param name="id"></param> /// <param name="language"></param> /// <returns></returns> public static StringArchive GetStringArchive(Archive baseArchive, ItemArchiveId id, Language language = Language.English) { Archive itemArchive = GetItemLanguageArchive(baseArchive, language); if (itemArchive == null) { return(null); } ArchiveRecord record = itemArchive.FindRecordById((int)id); if (record == null) { return(null); } Asset contents = record.Contents; return(contents as StringArchive); }
void CopyCSharpCodeToClipboard(object sender, EventArgs args) { StringBuilder builder = new StringBuilder(); int bitCount = 0; Dictionary <string, string> translatedShortNames = new Dictionary <string, string>(); Dictionary <string, string> translatedDescriptions = new Dictionary <string, string>(); #region Detect an unknown "_BOOL" type and report it. foreach (ParameterDefinitionRow row in Children) { if (row.DotNetType.EndsWith("_BOOL") || row.RealDotNetType.EndsWith("_BOOL")) { MessageBox.Show("This has an unhandled '_BOOL' type, the code will be wrong."); break; } } #endregion #region Read the translated names from the clipboard. if (Clipboard.ContainsText()) { string[] lines = Clipboard.GetText().TrimStart().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); if (lines.Length > 0 && lines[0] == JapaneseTranslationMarker) { for (int offset = 1; offset < lines.Length; offset += 4) { string id = lines[offset]; translatedShortNames[id] = lines.TryGet(offset + 1, ""); translatedDescriptions[id] = lines.TryGet(offset + 2, ""); } } } #endregion #region Print information to paste into various locations. builder.Append("/*\n"); builder.AppendFormat( "For ParameterTable.cs under {1}.ReadRow:\n" + " case TableRows.{0}.TableName: return new TableRows.{0}(table, index, loader, next);\n", Name, typeof(ParameterTableRow).Name); builder.AppendFormat( "For ParameterDefinition.cs under {0}.GetDotNetType():\n", typeof(ParameterDefinitionRow).Name); HashSet <string> unknownTypes = new HashSet <string>(); string enumerations = ""; foreach (ParameterDefinitionRow row in Children) { if (ParameterDefinitionRow.GetDotNetType(row.Type) == null && unknownTypes.Add(row.Type)) { builder.AppendFormat("\tcase \"{0}\": return typeof({0}).Name;\n", row.Type); enumerations += string.Format( "\n\t/// <summary></summary>\n" + "\t/// <remarks>\"{0}\" in Dark Souls.</remarks>\n" + "\tpublic enum {0} : {1} {{\n" + "\t}}\n", row.Type, row.RealDotNetType.ToLower()); } } if (enumerations != null) { builder.AppendFormat("For Enumerations.cs:{0}", enumerations); } builder.Append("*/\n"); #endregion builder.AppendFormat( "using Glare.Assets;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\n\n" + "namespace Alexandria.Engines.DarkSouls {{\n" + "\tpartial class TableRows {{\n"); if (LoadContext is ArchiveRecord) { ArchiveRecord record = (ArchiveRecord)LoadContext; builder.AppendFormat( "\t\t/// <summary></summary>\n" + "\t\t/// <remarks>\n" + "\t\t/// Defined as \"{0}\" in Dark Souls in the file \"{1}\" (id {2:X2}h).\n" + "\t\t/// </remarks>\n", Name, record.Name, record.Id); } builder.AppendFormat( "\t\tpublic class {0} : {1} {{\n" + "\t\t\tpublic const string TableName = \"{0}\";\n\n", Name, typeof(ParameterTableRow).Name); #region Print field definitions, grouping them up to make them easier to deal with. Dictionary <string, string> fieldDefinitions = new Dictionary <string, string>(); // Define the fields. foreach (ParameterDefinitionRow row in Children) { if (row.IsBitField) { continue; } string type = row.DotNetType; string name = row.DotNetFieldName; string current; fieldDefinitions[type] = fieldDefinitions.TryGetValue(type, out current) ? current + ", " + name : name; } // Print the field definitions. foreach (var item in fieldDefinitions) { builder.AppendFormat("\t\t\t{0} {1};\n", item.Key, item.Value); } builder.Append("\n"); #endregion #region Print the PropertyInfo declarations. builder.AppendFormat("\t\t\tpublic static readonly {0}\n", typeof(PropertyInfo).Name); foreach (ParameterDefinitionRow row in Children) { builder.AppendFormat("\t\t\t\t{0}Property = GetProperty<{1}>(\"{0}\"){2}\n", row.DotNetName, Name, row == Children[Children.Count - 1] ? ";" : ","); } builder.Append("\n"); #endregion #region Print the property definitions bitCount = 0; foreach (ParameterDefinitionRow row in Children) { string getProperty = "return " + row.DotNetFieldName + ";"; string setProperty = string.Format("SetProperty(ref {0}, ref value, {1}Property);", row.DotNetFieldName, row.DotNetName); if (row.IsBitField) { getProperty = string.Format("return {3}GetBitProperty({0}, {1}, {2}Property){4};", bitCount, row.BitFieldBits, row.DotNetName, row.IsBoolean ? "" : "(" + row.DotNetType + ")", row.IsBoolean ? " != 0" : ""); setProperty = string.Format("SetBitProperty({0}, {1}, {3}, {2}Property);", bitCount, row.BitFieldBits, row.DotNetName, row.IsBoolean ? "value ? 1 : 0" : "(int)value"); bitCount += row.BitFieldBits; } string translatedShortName = translatedShortNames.TryGetValue(row.DotNetName, ""); string translatedDescription = translatedDescriptions.TryGetValue(row.DotNetName, ""); builder.AppendFormat( "\t\t\t/// <summary>{0}</summary>\n" + "\t\t\t/// <remarks>\n" + "\t\t\t/// Japanese short name: \"{2}\", Google translated: \"{0}\".\n" + "\t\t\t/// Japanese description: \"{3}\", Google translated: \"{1}\".\n" + "\t\t\t/// </remarks>\n", translatedShortName, translatedDescription, // {0} and {1} row.JapaneseShortName, row.JapaneseDescription); // {2} and {3} builder.AppendFormat("\t\t\t[{0}(\"{1}\", index: {2}, @default: {3}, minimum: {4}, maximum: {5}, step: {6}, order: {7}, unknown2: {8})]\n", typeof(ParameterTableRowAttribute).Name, row.Name, row.Index, row.ValueDefault, row.ValueMinimum, row.ValueMaximum, row.ValueStep, row.UnknownValue1, row.UnknownValue2); builder.AppendFormat("\t\t\t[DisplayName(\"{0}\")]\n", translatedShortName.Replace("\"", "\\\"")); builder.AppendFormat("\t\t\t[Description(\"{0}\")]\n", translatedDescription.Replace("\"", "\\\"")); if (!row.IsArray) { builder.AppendFormat("\t\t\t[DefaultValue({0})]\n", row.CSharpValueDefault); } if (row.Type == "dummy8") { builder.AppendFormat("\t\t\t[Browsable(false)]\n"); } builder.AppendFormat("\t\t\tpublic {0} {1} {{\n", row.DotNetType, row.DotNetName); builder.AppendFormat("\t\t\t\tget {{ {0} }}\n", getProperty); if (!row.IsEnum && !row.IsBoolean && !row.IsArray) { builder.AppendFormat( "\t\t\t\tset {{\n" + "\t\t\t\t\tif((double)value < {1} || (double)value > {2})\n" + "\t\t\t\t\t\tthrow new ArgumentOutOfRangeException(\"value\", \"value of \" + value + \" is out of range {1} to {2} for \" + {0}Property.Name + \".\");\n" + "\t\t\t\t\t{3}\n" + "\t\t\t\t}}\n", row.DotNetName, row.ValueMinimum, row.ValueMaximum, setProperty); } else { builder.AppendFormat("\t\t\t\tset {{ {0} }}\n", setProperty); } builder.Append("\t\t\t}\n"); builder.Append("\n"); } #endregion #region Print the constructor builder.AppendFormat( "\t\t\tinternal {0}({1} table, int index, {2} loader, int next)\n" + "\t\t\t\t: base(table, index, loader) {{\n" + "\t\t\t\tBinaryReader reader = loader.Reader;\n\n", Name, typeof(ParameterTable).Name, typeof(AssetLoader).Name); bool bitsMode = false, hadBits = false; foreach (ParameterDefinitionRow row in Children) { if (row.IsBitField) { if (bitsMode == false) { if (hadBits) { MessageBox.Show("Multiple bit fields counted; code will not be correct."); } hadBits = true; bitsMode = true; bitCount = 0; for (int bitCounter = row.Index; bitCounter < Children.Count; bitCounter++) { ParameterDefinitionRow bitRow = (ParameterDefinitionRow)Children[bitCounter]; if (!bitRow.IsBitField) { continue; } bitCount += bitRow.BitFieldBits; } builder.AppendFormat("\t\t\t\tBitFields = reader.ReadBytes({0});\n", (bitCount + 7) / 8); } } else { bitsMode = false; if (row.DataType == "dummy8") { builder.AppendFormat("\t\t\t\t{0} = reader.ReadBytes({1});\n", row.DotNetName, row.Size); } else { builder.AppendFormat("\t\t\t\t{0} = {1}reader.Read{2}();\n", row.DotNetName, row.IsEnum ? "(" + row.DotNetType + ")" : "", row.RealDotNetType); } } } builder.Append("\t\t\t}\n\n"); #endregion #region Print the initialiser constructor. builder.AppendFormat( "\t\t\tinternal {0}({1} table, int index)\n" + "\t\t\t\t: base(table, index) {{\n", Name, typeof(ParameterTable).Name); if (bitCount > 0) { builder.AppendFormat("\t\t\t\tBitFields = new byte[{0}];\n", (bitCount + 7) / 8); } foreach (ParameterDefinitionRow row in Children) { builder.AppendFormat("\t\t\t\t{0} = {1};\n", row.DotNetName, row.CSharpValueDefault); } builder.Append("\t\t\t}\n\n"); #endregion #region Print the write method. builder.Append("\t\t\tpublic override void Write(BinaryWriter writer) {\n"); foreach (ParameterDefinitionRow row in Children) { if (row.IsBitField) { if (bitsMode == false) { bitsMode = true; builder.Append("\t\t\t\twriter.Write(BitFields);\n"); } } else { if (row.DataType == "dummy8") { builder.AppendFormat("\t\t\t\twriter.Write({0});\n", row.DotNetName); } else { builder.AppendFormat("\t\t\t\twriter.Write({0}{1});\n", row.IsEnum ? "(" + row.RealDotNetType + ")" : "", row.DotNetName); } } } builder.Append("\t\t\t}\n"); #endregion builder.Append("\t\t}\n"); builder.Append("\t}\n"); builder.Append("}\n"); Clipboard.Clear(); Clipboard.SetText(builder.ToString()); }