public void WriteNullable( MutagenWriter writer, ITranslatedStringGetter?item, RecordType header, StringBinaryType binaryType, StringsSource source) { if (item == null) { return; } try { using (HeaderExport.Header(writer, header, ObjectType.Subrecord)) { if (writer.MetaData.StringsWriter == null) { writer.Write( item.String ?? string.Empty, binaryType: binaryType); } else { writer.Write(writer.MetaData.StringsWriter.Register(item, source)); } } } catch (Exception ex) { throw SubrecordException.Factory(ex, header); } }
public uint Register(ITranslatedStringGetter str, StringsSource source) { List <KeyValuePair <Language, string>[]> strs = source switch { StringsSource.Normal => _strings, StringsSource.IL => _ilStrings, StringsSource.DL => _dlStrings, _ => throw new NotImplementedException(), }; lock (strs) { // ToDo // Add Count member to TranslatedString, or something similar to short circuit array creation if unnecessary var arr = str.ToArray(); if (!arr.Any(x => x.Value != null)) { // Do not insert into strings writer return(0); } strs.Add(arr); try { return(checked ((uint)strs.Count)); } catch (OverflowException) { throw new OverflowException("Too many translated strings for current system to handle."); } } }
public void WriteNullable( MutagenWriter writer, ITranslatedStringGetter?item, RecordType header, StringBinaryType binaryType, StringsSource source) { if (item == null) { return; } using (HeaderExport.Header(writer, header, ObjectType.Subrecord)) { if (writer.MetaData.StringsWriter == null) { writer.Write( item.String, binaryType: binaryType); } else { writer.Write(writer.MetaData.StringsWriter.Register(item, source)); } } }
public static bool TryRetrieveInfoFromString(ReadOnlySpan <char> name, out StringsSource source, out Language language, out ReadOnlySpan <char> modName) { source = default; language = default; modName = default; var extensionIndex = name.LastIndexOf('.'); if (extensionIndex == -1) { return(false); } if (!TryConvertToStringSource(name.Slice(extensionIndex + 1), out source)) { return(false); } var separatorIndex = name.LastIndexOf('_'); if (separatorIndex == -1) { return(false); } if (separatorIndex > extensionIndex) { return(false); } var languageSpan = name.Slice(separatorIndex + 1, extensionIndex - separatorIndex - 1); modName = name.Slice(0, separatorIndex); return(Enum.TryParse(languageSpan.ToString(), ignoreCase: true, out language)); }
public uint Register(ITranslatedStringGetter str, StringsSource source) { List <KeyValuePair <Language, string>[]> strs = source switch { StringsSource.Normal => _strings, StringsSource.IL => _ilStrings, StringsSource.DL => _dlStrings, _ => throw new NotImplementedException(), }; lock (strs) { var arr = str.ToArray(); if (!arr.Any(x => !string.IsNullOrEmpty(x.Value))) { // Do not insert into strings writer return(0); } strs.Add(arr); try { return(checked ((uint)strs.Count)); } catch (OverflowException) { throw new OverflowException("Too many translated strings for current system to handle."); } } }
public uint Register(string str, Language language, StringsSource source) { List <KeyValuePair <Language, string>[]> strs = source switch { StringsSource.Normal => _strings, StringsSource.IL => _ilStrings, StringsSource.DL => _dlStrings, _ => throw new NotImplementedException(), }; lock (strs) { strs.Add(new KeyValuePair <Language, string>[] { new KeyValuePair <Language, string>(language, str) }); try { return(checked ((uint)strs.Count)); } catch (OverflowException) { throw new OverflowException("Too many translated strings for current system to handle."); } } }
public static string GetFileName( StringsLanguageFormat languageFormat, ModKey modKey, Language language, StringsSource source) { return($"{modKey.Name}_{GetLanguageString(languageFormat, language)}.{GetSourceString(source)}"); }
private Dictionary <Language, Lazy <IStringsLookup> > Get(StringsSource source) { return(source switch { StringsSource.Normal => _strings, StringsSource.IL => _ilstrings, StringsSource.DL => _dlstrings, _ => throw new NotImplementedException(), });
public Dictionary <Language, Lazy <IStringsLookup> > Get(StringsSource source) { return(source switch { StringsSource.Normal => Strings, StringsSource.IL => IlStrings, StringsSource.DL => DlStrings, _ => throw new NotImplementedException(), });
public bool Parse( MutagenFrame frame, StringsSource source, StringBinaryType binaryType, out TranslatedString item, bool parseWhole = true) { item = Parse(frame, source, binaryType, parseWhole); return(true); }
/// <inheritdoc /> public bool TryLookup(StringsSource source, Language language, uint key, [MaybeNullWhen(false)] out string str) { var dict = Get(source); if (!dict.TryGetValue(language, out var lookup)) { str = default; return(false); } return(lookup.Value.TryLookup(key, out str)); }
public static StringsFileFormat GetFormat(StringsSource source) { switch (source) { case StringsSource.Normal: return(StringsFileFormat.Normal); case StringsSource.IL: case StringsSource.DL: return(StringsFileFormat.LengthPrepended); default: throw new NotImplementedException(); } }
public void Write( MutagenWriter writer, ITranslatedStringGetter item, RecordType header, StringBinaryType binaryType, StringsSource source) { using (HeaderExport.Header(writer, header, ObjectType.Subrecord)) { Write( writer, item, binaryType, source); } }
public static string GetSourceString(StringsSource source) { switch (source) { case StringsSource.Normal: return(StringsFileExtension); case StringsSource.IL: return(ILStringsFileExtension); case StringsSource.DL: return(DLStringsFileExtension); default: throw new NotImplementedException(); } }
public void Write( MutagenWriter writer, ITranslatedStringGetter item, StringBinaryType binaryType, StringsSource source) { if (writer.MetaData.StringsWriter == null) { writer.Write( item.String, binaryType: binaryType); } else { writer.Write(writer.MetaData.StringsWriter.Register(item, source)); } }
public static bool TryConvertToStringSource(ReadOnlySpan <char> str, out StringsSource source) { if (str.Equals(StringsFileExtension, StringComparison.OrdinalIgnoreCase)) { source = StringsSource.Normal; return(true); } if (str.Equals(ILStringsFileExtension, StringComparison.OrdinalIgnoreCase)) { source = StringsSource.IL; return(true); } if (str.Equals(DLStringsFileExtension, StringComparison.OrdinalIgnoreCase)) { source = StringsSource.DL; return(true); } source = default; return(false); }
public void WriteNullable( MutagenWriter writer, ITranslatedStringGetter?item, StringBinaryType binaryType, StringsSource source) { if (item == null) { return; } if (writer.MetaData.StringsWriter == null) { writer.Write( item.String ?? string.Empty, binaryType: binaryType); } else { writer.Write(writer.MetaData.StringsWriter.Register(item, source)); } }
public void Write( MutagenWriter writer, ITranslatedStringGetter item, RecordType header, StringBinaryType binaryType, StringsSource source) { try { using (HeaderExport.Header(writer, header, ObjectType.Subrecord)) { Write( writer, item, binaryType, source); } } catch (Exception ex) { throw SubrecordException.Factory(ex, header); } }
public TranslatedString Parse( ReadOnlyMemorySlice <byte> data, StringsSource source, IStringsFolderLookup?lookup) { if (lookup != null) { if (data.Length != 4) { throw new ArgumentException($"String in Strings File format had unexpected length: {data.Length} != 4"); } uint key = BinaryPrimitives.ReadUInt32LittleEndian(data); if (key == 0) { return(string.Empty); } return(lookup.CreateString(source, key)); } else { return(BinaryStringUtility.ProcessWholeToZString(data)); } }
public virtual TranslatedString Parse( MutagenFrame frame, StringsSource source, StringBinaryType stringBinaryType, bool parseWhole = true) { if (frame.MetaData.StringsLookup != null) { if (frame.Remaining != 4) { throw new ArgumentException($"String in Strings File format had unexpected length: {frame.Remaining} != 4"); } uint key = frame.ReadUInt32(); if (key == 0) { return(string.Empty); } return(frame.MetaData.StringsLookup.CreateString(source, key)); } else { return(Parse(frame, parseWhole, stringBinaryType)); } }
public TranslatedString Parse( MutagenFrame reader, StringsSource source, StringBinaryType stringBinaryType, bool parseWhole = true) { if (reader.MetaData.StringsLookup != null) { if (reader.Remaining != 4) { throw new ArgumentException($"String in Strings File format had unexpected length: {reader.Remaining} != 4"); } uint key = reader.ReadUInt32(); if (key == 0) { return(new TranslatedString(directString: null)); } return(reader.MetaData.StringsLookup.CreateString(source, key)); } else { return(Parse(reader, parseWhole, stringBinaryType)); } }
private async Task ProcessStringsFilesIndices( Func <IMutagenReadStream> streamGetter, DirectoryInfo dataFolder, Language language, StringsSource source, ModKey modKey, HashSet <uint> knownDeadKeys, IEnumerable <string> bsaOrder) { using var stream = streamGetter(); switch (source) { case StringsSource.Normal: ProcessStringsFiles( GameRelease.Fallout4, modKey, dataFolder, language, StringsSource.Normal, strict: false, knownDeadKeys: knownDeadKeys, bsaOrder: bsaOrder, RenumberStringsFileEntries( GameRelease.Fallout4, modKey, stream, dataFolder, language, StringsSource.Normal, new StringsAlignmentCustom("GMST", GameSettingStringHandler), new RecordType[] { "KYWD", "FULL" } )); break; //case StringsSource.DL: // ProcessStringsFiles( // modKey, // dataFolder, // language, // StringsSource.DL, // strict: true, // RenumberStringsFileEntries( // modKey, // stream, // dataFolder, // language, // StringsSource.DL, // new RecordType[] { "SCRL", "DESC" }, // )); // break; //case StringsSource.IL: // ProcessStringsFiles( // modKey, // dataFolder, // language, // StringsSource.IL, // strict: true, // RenumberStringsFileEntries( // modKey, // stream, // dataFolder, // language, // StringsSource.IL, // new RecordType[] { "DIAL" }, // new RecordType[] { "INFO", "NAM1" } // )); // break; } }
private async Task ProcessStringsFilesIndices(Func <IMutagenReadStream> streamGetter, DirectoryInfo dataFolder, Language language, StringsSource source, ModKey modKey) { using var stream = streamGetter(); switch (source) { case StringsSource.Normal: ProcessStringsFiles( modKey, dataFolder, language, StringsSource.Normal, strict: true, RenumberStringsFileEntries( modKey, stream, dataFolder, language, StringsSource.Normal, new StringsAlignmentCustom("GMST", GameSettingStringHandler), new RecordType[] { "LSCR", "DESC" }, new RecordType[] { "ACTI", "FULL", "RNAM" }, new RecordType[] { "APPA", "FULL" }, new RecordType[] { "AMMO", "FULL" }, new RecordType[] { "ARMO", "FULL" }, new RecordType[] { "BOOK", "FULL" }, new RecordType[] { "CLAS", "FULL" }, new RecordType[] { "EYES", "FULL" }, new RecordType[] { "CONT", "FULL" }, new RecordType[] { "DOOR", "FULL" }, new RecordType[] { "FACT", "FULL", "MNAM", "FNAM" }, new RecordType[] { "FURN", "FULL" }, new RecordType[] { "HAZD", "FULL" }, new RecordType[] { "HDPT", "FULL" }, new RecordType[] { "ALCH", "FULL" }, new RecordType[] { "INGR", "FULL" }, new RecordType[] { "LIGH", "FULL" }, new RecordType[] { "MGEF", "FULL", "DNAM" }, new RecordType[] { "MISC", "FULL" }, new RecordType[] { "MSTT", "FULL" }, new RecordType[] { "NPC_", "FULL", "SHRT" }, new RecordType[] { "ENCH", "FULL" }, new RecordType[] { "PROJ", "FULL" }, new RecordType[] { "RACE", "FULL" }, new RecordType[] { "SCRL", "FULL" }, new RecordType[] { "SLGM", "FULL" }, new RecordType[] { "SPEL", "FULL" }, new RecordType[] { "TACT", "FULL" }, new RecordType[] { "TREE", "FULL" }, new RecordType[] { "WEAP", "FULL" }, new RecordType[] { "FLOR", "FULL", "RNAM" }, new RecordType[] { "KEYM", "FULL" }, new RecordType[] { "CELL", "FULL" }, new RecordType[] { "REFR", "FULL" }, new RecordType[] { "WRLD", "FULL" }, new RecordType[] { "DIAL", "FULL" }, new RecordType[] { "INFO", "RNAM" }, new RecordType[] { "QUST", "FULL", "NNAM" }, new RecordType[] { "WATR", "FULL" }, new RecordType[] { "EXPL", "FULL" }, new StringsAlignmentCustom("PERK", PerkStringHandler), new RecordType[] { "BPTD", "BPTN" }, new RecordType[] { "AVIF", "FULL" }, new RecordType[] { "LCTN", "FULL" }, new RecordType[] { "MESG", "FULL", "ITXT" }, new RecordType[] { "WOOP", "FULL", "TNAM" }, new RecordType[] { "SHOU", "FULL" }, new RecordType[] { "SNCT", "FULL" }, new RecordType[] { "CLFM", "FULL" }, new RecordType[] { "REGN", "RDMP" } )); break; case StringsSource.DL: ProcessStringsFiles( modKey, dataFolder, language, StringsSource.DL, strict: true, RenumberStringsFileEntries( modKey, stream, dataFolder, language, StringsSource.DL, new RecordType[] { "SCRL", "DESC" }, new RecordType[] { "APPA", "DESC" }, new RecordType[] { "AMMO", "DESC" }, new RecordType[] { "ARMO", "DESC" }, new RecordType[] { "ALCH", "DESC" }, new RecordType[] { "WEAP", "DESC" }, new RecordType[] { "BOOK", "DESC", "CNAM" }, new RecordType[] { "QUST", "CNAM" }, new RecordType[] { "PERK", "DESC" }, new RecordType[] { "AVIF", "DESC" }, new RecordType[] { "MESG", "DESC" }, new RecordType[] { "SHOU", "DESC" }, new RecordType[] { "COLL", "DESC" }, new RecordType[] { "RACE", "DESC" }, new RecordType[] { "SPEL", "DESC" } )); break; case StringsSource.IL: ProcessStringsFiles( modKey, dataFolder, language, StringsSource.IL, strict: true, RenumberStringsFileEntries( modKey, stream, dataFolder, language, StringsSource.IL, new RecordType[] { "DIAL" }, new RecordType[] { "INFO", "NAM1" } )); break; } }
private void WriteStrings(List <KeyValuePair <Language, string>[]> strs, StringsSource source) { if (strs.Count == 0) { return; } WriteDir.Create(); var subLists = new Dictionary <Language, List <(string String, int Index)> >(); for (int i = 0; i < strs.Count; i++) { var item = strs[i]; foreach (var lang in item) { if (!subLists.TryGetValue(lang.Key, out var list)) { list = new List <(string String, int Index)>(); subLists[lang.Key] = list; } list.Add((lang.Value, i + 1)); } } foreach (var language in subLists) { using var writer = new MutagenWriter( Path.Combine(WriteDir.Path, StringsUtility.GetFileName(_modKey, language.Key, source)), meta: null !); // Write count writer.Write(language.Value.Count); // Write filler for length later writer.WriteZeros(4); // Write Directory int size = 0; foreach (var item in language.Value) { writer.Write(item.Index); switch (source) { case StringsSource.Normal: writer.Write(size); size += item.String.Length + 1; break; case StringsSource.IL: case StringsSource.DL: writer.Write(size); size += item.String.Length + 5; break; default: throw new NotImplementedException(); } } // Go back and write content length; var pos = writer.Position; writer.Position = 4; writer.Write(size); writer.Position = pos; // Write strings foreach (var item in language.Value) { switch (source) { case StringsSource.Normal: writer.Write(item.String, StringBinaryType.NullTerminate); break; case StringsSource.IL: case StringsSource.DL: writer.Write(item.String.Length + 1); writer.Write(item.String, StringBinaryType.NullTerminate); break; default: throw new NotImplementedException(); } } } }
public static string GetFileName(ModKey modKey, Language language, StringsSource source) { return($"{modKey.Name}_{language}.{GetSourceString(source)}"); }
/// <summary> /// Overlays onto a set of bytes assumed to be in Strings file format /// </summary> /// <param name="data">Data to wrap</param> /// <param name="source">Source type</param> public StringsLookupOverlay(ReadOnlyMemorySlice <byte> data, StringsSource source) { Init(data, StringsUtility.GetFormat(source)); }
/// <summary> /// Reads all bytes from a file, and overlays them /// </summary> /// <param name="path">Path to read in</param> /// <param name="source">Source type</param> public StringsLookupOverlay(string path, StringsSource source) { Init(File.ReadAllBytes(path), StringsUtility.GetFormat(source)); }
public ManualStringsLookup( StringsSource source, params (Language Language, uint Key, string Str)[] strs)