/// <summary> /// Applies translations to content.ggpk /// </summary> public void ApplyTranslations() { StringBuilder outputBuffer = new StringBuilder(); foreach (var datTranslation in AllDatTranslations) { // Map of originalText -> Translation containing all translations to apply Dictionary <string, Translation> translationsToApply = (from n in datTranslation.Value.Translations where n.Status == Translation.TranslationStatus.NeedToApply select n).ToDictionary(k => k.OriginalText); if (translationsToApply.Count == 0) { continue; } // Record we will be translating with data from translationTable FileRecord datRecord = fileRecordMap[datTranslation.Value.DatName]; // Raw bytes of the .dat file we will be translating byte[] datBytes = datRecord.ReadData(ggpkPath); // Dat parser for changing the actual strings DatContainer dc = new DatContainer(new MemoryStream(datBytes), datTranslation.Value.DatName); // Replace the actual strings foreach (var item in dc.DataEntries) { UnicodeString currentDatString = (item.Value as UnicodeString); if (currentDatString == null || !currentDatString.IsUserString) { continue; } if (!translationsToApply.ContainsKey(currentDatString.Data)) { continue; } Translation translationBeingApplied = translationsToApply[currentDatString.Data]; currentDatString.NewData = translationBeingApplied.TranslatedText; outputBuffer.AppendLine(string.Format(Settings.Strings["ApplyTranslations_TextReplaced"], translationBeingApplied.ShortNameCurrent, translationBeingApplied.ShortNameTranslated)); translationBeingApplied.Status = Translation.TranslationStatus.AlreadyApplied; } // dc.GetBytes() will return the new data for this .dat file after replacing the original strings with whatever's in 'NewData' datRecord.ReplaceContents(ggpkPath, dc.GetBytes(), content.FreeRoot); } if (outputBuffer.Length > 0) { Output(outputBuffer.ToString()); } }
/// <summary> /// Applies translations to content.ggpk /// </summary> public void ApplyTranslations() { var outputBuffer = new StringBuilder(); foreach (var datTranslation in AllDatTranslations) { // Map of originalText -> Translation containing all translations to apply var translationsToApply = (from n in datTranslation.Value.Translations where n.Status == Translation.TranslationStatus.NeedToApply select n).ToDictionary(k => k.OriginalText); if (translationsToApply.Count == 0) { continue; } // Record we will be translating with data from translationTable var datRecord = fileRecordMap[datTranslation.Value.DatName]; // Raw bytes of the .dat file we will be translating var datBytes = datRecord.ReadFileContent(ggpkPath); // Dat parser for changing the actual strings var dc = new DatContainer(new MemoryStream(datBytes), datTranslation.Value.DatName); // Replace the actual strings var strings = dc.GetUserStrings(); foreach (var currentDatString in strings) { if (!translationsToApply.ContainsKey(currentDatString.Value)) { continue; } // TODO skip already strings already procesed in this loops var translationBeingApplied = translationsToApply[currentDatString.Value]; currentDatString.NewValue = translationBeingApplied.TranslatedText; outputBuffer.AppendLine(string.Format( Settings.Strings["ApplyTranslations_TextReplaced"], translationBeingApplied.ShortNameCurrent, translationBeingApplied.ShortNameTranslated)); translationBeingApplied.Status = Translation.TranslationStatus.AlreadyApplied; } // dc.SaveAsBytes() will return the new data for this .dat file after replacing the original strings with whatever's in 'NewData' content.ReplaceFile(datRecord, dc.SaveAsBytes()); } if (outputBuffer.Length > 0) { Output(outputBuffer.ToString()); } }
public ListType(BinaryReader Reader, DatContainer dat, string ListDataType, long Count) : base(dat?.x64 ?? false) { Values = new((int)Count); for (var i = 0L; i < Count; i++) { Values.Add(Create(ListDataType, Reader, dat)); } if (Count > 0) { Type = Values[0].Type; } }
/// <summary> /// Read a <see cref="StringData"/> from its value in string representation /// </summary> public static StringData FromString(string value, DatContainer dat) { if (dat.ReferenceDataOffsets.TryGetValue(value, out long offset) && dat.ReferenceDatas.TryGetValue(offset, out IReferenceData? rd) && rd is StringData s) { return(s); } var sd = new StringData(dat); sd.FromString(value); return(sd); }
public static FieldType Create(string type, BinaryReader reader, DatContainer dat) { if (type == "ref|key") { return(new KeyType(dat.x64, reader, false)); } else if (type == "ref|foreignkey") { return(new KeyType(dat.x64, reader, true)); } else if (type.StartsWith("ref|")) { return(new PointerType(reader, dat.x64, dat, type[4..]));
/// <summary> /// Read a <see cref="ArrayData{TypeOfValueInArray}"/> from its value in string representation /// </summary> public static ArrayData <TypeOfValueInArray> FromString(string value, DatContainer dat, FieldType typeOfarrayInArray) { value = typeOfarrayInArray == FieldType.String || typeOfarrayInArray == FieldType.ValueString ? value : Regex.Replace(value, @"\s", "").Replace(",", ", "); if (dat.ReferenceDataOffsets.TryGetValue(value, out long offset) && dat.ReferenceDatas.TryGetValue(offset, out IReferenceData? rd) && rd is ArrayData <TypeOfValueInArray> a) { return(a); } var ad = new ArrayData <TypeOfValueInArray>(dat, typeOfarrayInArray); ad.FromString(value); return(ad); }
public ListType(BinaryReader Reader, DatContainer dat, string ListDataType, long Count) : base(dat?.x64 ?? false) { Values = new((int)Count); for (var i = 0L; i < Count; i++) { var t = Create(ListDataType, Reader, dat); if (t is KeyType k && (k.EOF1 || k.EOF2)) { throw new EndOfStreamException(); } Values.Add(t); } }
/// <summary> /// Read a <see cref="StringData"/> from a dat file /// </summary> public static StringData Read(BinaryReader reader, DatContainer dat) { var offset = dat.x64 ? reader.ReadInt64() : reader.ReadInt32(); if (dat.ReferenceDatas.TryGetValue(offset, out IReferenceData? rd) && rd is StringData s) { return(s); } reader.BaseStream.Seek(dat.x64 ? -8 : -4, SeekOrigin.Current); var sd = new StringData(dat); sd.Read(reader); return(sd); }
/// <summary> /// Gets a list of all translatable strings in specified record. Record must be a FileRecord of a valid dat file. /// </summary> /// <param name="record">Dat File Record to extract translatable strings from</param> /// <returns>List of translatable strings contained in specified dat file</returns> private List <string> GetTranslatableStringsFromDatFile(FileRecord record) { // Map of all strings that can be safely translated (not used as ID's, paths, etc) stored by their hash var resultList = new HashSet <string>(); var datBytes = record.ReadFileContent(ggpkPath); using (var datStream = new MemoryStream(datBytes)) { var dc = new DatContainer(datStream, record.Name); var strings = dc.GetUserStrings(); foreach (var currentDatString in strings) { resultList.Add(currentDatString.GetValueString()); } } return(resultList.ToList()); }
public static string ConvertDatToCSV(string file) { try { var dat = new DatContainer(file); var csvData = dat.GetCsvFormat(); if (csvData == null) { throw new Exception("ConvertDatToCSV Error,is DatDefinitions.xml exist?"); } return(csvData); } catch (Exception e) { throw; } }
private void ParseDatFile(Stream inStream) { try { _dat = new DatContainer(inStream, _datName); var containerData = DataEntries.ToList(); var userStringOffsets = _dat.GetUserStringOffsets(); foreach (var keyValuePair in containerData) { var data = keyValuePair.Value; var isUser = userStringOffsets.Contains(keyValuePair.Key); Strings.Add(new DatString(data, isUser)); } } catch (Exception ex) { throw new Exception(string.Format(Settings.Strings["DatWrapper_ParseDatFile_Failed"], ex.ToString()), ex); } }
/// <summary> /// Gets a list of all translatable strings in specified record. Record must be a FileRecord of a valid dat file. /// </summary> /// <param name="record">Dat File Record to extract translatable strings from</param> /// <returns>List of translatable strings contained in specified dat file</returns> private List <string> GetTranslatableStringsFromDatFile(FileRecord record) { // Map of all strings that can be safely translated (not used as ID's, paths, etc) stored by their hash HashSet <string> currentStrings = new HashSet <string>(); byte[] datBytes = record.ReadData(ggpkPath); using (MemoryStream datStream = new MemoryStream(datBytes)) { DatContainer container = new DatContainer(datStream, record.Name); // Any properties with the UserStringIndex attribute are translatable foreach (var propInfo in container.DatType.GetProperties()) { if (!propInfo.GetCustomAttributes(false).Any(n => n is UserStringIndex)) { continue; } foreach (var entry in container.Entries) { int stringIndex = (int)propInfo.GetValue(entry, null); string stringValue = container.DataEntries[stringIndex].ToString(); if (string.IsNullOrWhiteSpace(stringValue)) { continue; } if (!currentStrings.Contains(stringValue)) { currentStrings.Add(stringValue); } } } } return(currentStrings.ToList()); }
/// <summary> /// Read a <see cref="ArrayData{TypeOfValueInArray}"/> from a dat file /// </summary> public static ArrayData <TypeOfValueInArray> Read(BinaryReader reader, DatContainer dat, FieldType typeOfarrayInArray) { long length; long offset; if (dat.x64) { length = reader.ReadInt64(); offset = reader.ReadInt64(); } else { length = reader.ReadInt32(); offset = reader.ReadInt32(); } if (typeOfarrayInArray == FieldType.Unknown || length == 0) { return new(dat, typeOfarrayInArray) { Value = Array.Empty <TypeOfValueInArray>(), Offset = offset, Length = (int)length } } ; if (dat.ReferenceDatas.TryGetValue(offset, out IReferenceData? rd) && rd is ArrayData <TypeOfValueInArray> a) { return(a); } reader.BaseStream.Seek(dat.x64 ? -16 : -8, SeekOrigin.Current); var ad = new ArrayData <TypeOfValueInArray>(dat, typeOfarrayInArray); ad.Read(reader); return(ad); }
private void ParseDatFile(Stream inStream) { Dat = new DatContainer(inStream, datName); try { var containerData = DataEntries.ToList(); foreach (var keyValuePair in containerData) { if (keyValuePair.Value is UnicodeString) { Strings.Add((UnicodeString)keyValuePair.Value); } else if (keyValuePair.Value is UInt64List) { UInt64List ul = (UInt64List)keyValuePair.Value; Strings.Add((UnicodeString) new UnicodeString(ul.Offset, ul.dataTableOffset, ul.ToString())); } else if (keyValuePair.Value is UInt32List) { UInt32List ul = (UInt32List)keyValuePair.Value; Strings.Add((UnicodeString) new UnicodeString(ul.Offset, ul.dataTableOffset, ul.ToString())); } else if (keyValuePair.Value is Int32List) { Int32List ul = (Int32List)keyValuePair.Value; Strings.Add((UnicodeString) new UnicodeString(ul.Offset, ul.dataTableOffset, ul.ToString())); } } } catch (Exception ex) { throw new Exception(string.Format(Settings.Strings["DatWrapper_ParseDatFile_Failed"], ex.Message), ex); } }
public UInt8Data(DatContainer dat) : base(dat) { }
public Float32Data(DatContainer dat) : base(dat) { }
/// <summary> /// Creates for each given .dat files it's .csv analogue /// </summary> /// <param name="files"></param> private void ConvertFiles(List <string> files) { if (files == null) { return; } ButtonSelectFolderEnnabled = false; ButtonSelectFilesEnabled = false; var taskAction = new Action(() => { foreach (var file in files) { try { var dat = new DatContainer(file); var csvData = dat.GetCsvFormat(); var csvName = file + ".csv"; File.WriteAllText(csvName, csvData); OutputLine(String.Format("Success: {0}", file)); // stats var fileName = Path.GetFileName(file); if (dat.RecordInfo.Fields.Count > 0) { _lengths[fileName] = dat.Records.Count; } else { _counts[fileName] = dat.Count; } } catch (Exception e) { OutputLine(String.Format("Error: {0}\n\t{1}", file, e.Message)); } } OutputLine("\nFinished."); }); var taskFinished = new Action <Task>(t => { ButtonSelectFolderEnnabled = true; ButtonSelectFilesEnabled = true; var tmp100 = new Dictionary <string, string>(); var tmp1000 = new Dictionary <string, string>(); var tmp10000 = new Dictionary <string, string>(); foreach (var kv in _lengths) { if (kv.Value < 100) { tmp100[kv.Key] = String.Format("{0}\t{1,-7}\t{2}", 0, kv.Value, kv.Key); } else if (kv.Value < 1000) { tmp1000[kv.Key] = String.Format("{0}\t{1,-7}\t{2}", 0, kv.Value, kv.Key); } else { tmp10000[kv.Key] = String.Format("{0}\t{1,-7}\t{2}", 0, kv.Value, kv.Key); } } // 1000+ records var sortedFiles = tmp10000.Keys.ToList(); sortedFiles.Sort(); foreach (var s in sortedFiles) { OutputLine(tmp10000[s]); } OutputLine(""); // 100+ records sortedFiles = tmp1000.Keys.ToList(); sortedFiles.Sort(); foreach (var s in sortedFiles) { OutputLine(tmp1000[s]); } OutputLine(""); // <100 records sortedFiles = tmp100.Keys.ToList(); sortedFiles.Sort(); foreach (var s in sortedFiles) { OutputLine(tmp100[s]); } OutputLine(""); // no recors sortedFiles = _counts.Keys.ToList(); sortedFiles.Sort(); foreach (var s in sortedFiles) { OutputLine(String.Format("{0}\t{1,-7}\t{2}", _counts[s], 0, s)); } } ); var task = new Task(taskAction); task.ContinueWith(taskFinished); task.Start(); }
public ArrayData(DatContainer dat, FieldType typeOfValue) : base(dat) { TypeOfValue = typeOfValue; }
public StringData(DatContainer dat) : base(dat) { }
/// <summary> /// TreeView selected changed event /// </summary> private void OnTreeSelectedChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { if (Tree.SelectedItem is TreeViewItem tvi) { ImageView.Visibility = Visibility.Hidden; TextView.Visibility = Visibility.Hidden; //OGGView.Visibility = Visibility.Hidden; DatView.Visibility = Visibility.Hidden; //BK2View.Visibility = Visibility.Hidden; //BANKView.Visibility = Visibility.Hidden; ButtonSave.Visibility = Visibility.Hidden; if (tvi.Tag is RecordTreeNode rtn) { TextBoxOffset.Text = rtn.Offset.ToString("X"); TextBoxSize.Text = rtn.Length.ToString(); TextBoxHash.Text = rtn is DirectoryRecord || rtn is FileRecord?BitConverter.ToString(rtn.Hash).Replace("-", "") : rtn is BundleFileNode bf?bf.Hash.ToString("X") : ((BundleDirectoryNode)rtn).Hash.ToString("X"); TextBoxBundle.Text = ""; if (rtn is IFileRecord f) { if (f is FileRecord fr) { TextBoxSize.Text = fr.DataLength.ToString(); } else { TextBoxBundle.Text = ((BundleFileNode)f).BundleFileRecord.bundleRecord.Name; } switch (f.DataFormat) { case IFileRecord.DataFormats.Image: ImageView.Source = BitmapFrame.Create(new MemoryStream(f.ReadFileContent(ggpkContainer.fileStream))); ImageView.Visibility = Visibility.Visible; break; case IFileRecord.DataFormats.Ascii: TextView.IsReadOnly = false; TextView.Text = UTF8.GetString(f.ReadFileContent(ggpkContainer.fileStream)); TextView.Visibility = Visibility.Visible; ButtonSave.Visibility = Visibility.Visible; break; case IFileRecord.DataFormats.Unicode: if (rtn.Parent.Name == "Bundles") { goto case IFileRecord.DataFormats.Ascii; } TextView.IsReadOnly = false; TextView.Text = Unicode.GetString(f.ReadFileContent(ggpkContainer.fileStream)).TrimStart('\xFEFF'); TextView.Visibility = Visibility.Visible; ButtonSave.Visibility = Visibility.Visible; break; case IFileRecord.DataFormats.OGG: //TODO //OGGView.Visibility = Visibility.Visible; break; case IFileRecord.DataFormats.Dat: try { var dat = new DatContainer(f.ReadFileContent(ggpkContainer.fileStream), rtn.Name); ShowDatFile(dat); DatView.Visibility = Visibility.Visible; } catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); } break; case IFileRecord.DataFormats.TextureDds: try { var buffer = f.ReadFileContent(ggpkContainer.fileStream); if (rtn.Name.EndsWith(".header")) { buffer = buffer[16..];
public RowData(DatContainer dat) : base(dat) { Value = this; }
/// <summary> /// Applies translations to content.ggpk /// </summary> public void ApplyTranslationsToFile() { StringBuilder outputBuffer = new StringBuilder(); foreach (var datTranslation in AllDatTranslations) { if (datTranslation.Value.Translations == null) { continue; } // Map of originalText -> Translation containing all translations to apply var translationsToApply = (from n in datTranslation.Value.Translations where n.Status == Translation.TranslationStatus.NeedToApply select n).ToDictionary(k => k.OriginalText); if (translationsToApply.Count == 0) { continue; } // Record we will be translating with data from translationTable var datRecord = fileRecordMap[datTranslation.Value.DatName]; // Raw bytes of the .dat file we will be translating var datBytes = datRecord.ReadFileContent(ggpkPath); // Dat parser for changing the actual strings var dc = new DatContainer(new MemoryStream(datBytes), datTranslation.Value.DatName); // Replace the actual strings var strings = dc.GetUserStrings(); foreach (var currentDatString in strings) { if (!translationsToApply.ContainsKey(currentDatString.Value)) { continue; } var translationBeingApplied = translationsToApply[currentDatString.Value]; currentDatString.NewValue = translationBeingApplied.TranslatedText; outputBuffer.AppendLine(string.Format( Settings.Strings["ApplyTranslations_TextReplaced"], translationBeingApplied.ShortNameCurrent, translationBeingApplied.ShortNameTranslated)); translationBeingApplied.Status = Translation.TranslationStatus.AlreadyApplied; } string subPath = "Data"; bool exists = System.IO.Directory.Exists(subPath); if (!exists) { System.IO.Directory.CreateDirectory(subPath); } string patched = "Data/" + datTranslation.Value.DatName; dc.Save(patched); } if (outputBuffer.Length > 0) { Output(outputBuffer.ToString()); } }
public Int16Data(DatContainer dat) : base(dat) { }
public ReferenceDataBase(DatContainer dat) : base(dat) { }
public BooleanData(DatContainer dat) : base(dat) { }