From 1fde9b981ebe7272551cc1f044f193bc6aff72a1 Mon Sep 17 00:00:00 2001 From: aianlinb Date: Wed, 25 Dec 2019 19:58:14 +0800 Subject: [PATCH 1/3] New program: DatEditer written in VB --- DatEditer/App.config | 6 + DatEditer/DatEditer.vbproj | 126 +++++++++++++++ DatEditer/DatWrapper.vb | 152 +++++++++++++++++++ DatEditer/Form1.Designer.vb | 114 ++++++++++++++ DatEditer/Form1.resx | 126 +++++++++++++++ DatEditer/Form1.vb | 28 ++++ DatEditer/My Project/Application.Designer.vb | 38 +++++ DatEditer/My Project/Application.myapp | 10 ++ DatEditer/My Project/AssemblyInfo.vb | 35 +++++ DatEditer/My Project/Resources.Designer.vb | 62 ++++++++ DatEditer/My Project/Resources.resx | 117 ++++++++++++++ DatEditer/My Project/Settings.Designer.vb | 73 +++++++++ DatEditer/My Project/Settings.settings | 7 + 13 files changed, 894 insertions(+) create mode 100644 DatEditer/App.config create mode 100644 DatEditer/DatEditer.vbproj create mode 100644 DatEditer/DatWrapper.vb create mode 100644 DatEditer/Form1.Designer.vb create mode 100644 DatEditer/Form1.resx create mode 100644 DatEditer/Form1.vb create mode 100644 DatEditer/My Project/Application.Designer.vb create mode 100644 DatEditer/My Project/Application.myapp create mode 100644 DatEditer/My Project/AssemblyInfo.vb create mode 100644 DatEditer/My Project/Resources.Designer.vb create mode 100644 DatEditer/My Project/Resources.resx create mode 100644 DatEditer/My Project/Settings.Designer.vb create mode 100644 DatEditer/My Project/Settings.settings diff --git a/DatEditer/App.config b/DatEditer/App.config new file mode 100644 index 0000000..321649d --- /dev/null +++ b/DatEditer/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DatEditer/DatEditer.vbproj b/DatEditer/DatEditer.vbproj new file mode 100644 index 0000000..7e64191 --- /dev/null +++ b/DatEditer/DatEditer.vbproj @@ -0,0 +1,126 @@ + + + + + Debug + AnyCPU + {6601B7A5-54D8-4E39-864C-FA5436FE5E74} + WinExe + DatEditer.My.MyApplication + DatEditer + DatEditer + 512 + WindowsForms + v4.6.1 + true + true + + + AnyCPU + true + full + true + true + bin\Debug\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + false + + + AnyCPU + pdbonly + false + true + true + bin\Release\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + + + + + + + + + + + + + + + + + + + Form + + + Form1.vb + Form + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + Form1.vb + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + {8f9fc78e-6181-4447-ac45-56173c16a0fa} + LibDat + + + + \ No newline at end of file diff --git a/DatEditer/DatWrapper.vb b/DatEditer/DatWrapper.vb new file mode 100644 index 0000000..7ae8112 --- /dev/null +++ b/DatEditer/DatWrapper.vb @@ -0,0 +1,152 @@ +Imports System.Collections.Generic +Imports System.IO +Imports System.Linq +Imports System.Text +Imports LibDat +Imports LibDat.Data + +Namespace VisualGGPK + Public Class DatString + Private _data As AbstractData + + Public ReadOnly Property DataType As String + Get + Return _data.GetType().ToString().Replace("LibDat.Data.", "") + End Get + End Property + + Public ReadOnly Property OffsetStart As Integer + Get + Return _data.Offset + End Get + End Property + + Public ReadOnly Property OffsetEnd As Integer + Get + Return _data.Offset + _data.Length + End Get + End Property + + Public ReadOnly Property Length As Integer + Get + Return _data.Length + End Get + End Property + + Public ReadOnly Property IsUser As Boolean + + Public Property NewValue As String + Get + Dim str = TryCast(_data, StringData) + If Not IsNothing(str) Then + Return str.NewValue + Else + Return "" + End If + End Get + Set(value As String) + DirectCast(_data, StringData).NewValue = value + End Set + End Property + + Public ReadOnly Property Value As String + Get + Return _data.GetValueString() + End Get + End Property + + Public Sub New(Data As AbstractData, isUser As Boolean) + _data = Data + Me.IsUser = isUser + End Sub + End Class + + Public Class DatWrapper + + Private _datName As String + Private _dat As DatContainer + + Public ReadOnly Property RecordInfo As RecordInfo + Get + Return _dat.RecordInfo + End Get + End Property + + Public ReadOnly Property DataSectionffset As Long + Get + Return DatContainer.DataSectionOffset + End Get + End Property + + Public ReadOnly Property DataSectionDataLength As Long + Get + Return _dat.DataSectionDataLength + End Get + End Property + + Public ReadOnly Property Records As List(Of RecordData) + Get + Return _dat.Records + End Get + End Property + + Public ReadOnly Property DataEntries As Dictionary(Of Integer, AbstractData) + Get + Return DatContainer.DataEntries + End Get + End Property + + Private _dataStrings As New List(Of DatString) + Public ReadOnly Property Strings As List(Of DatString) + Get + Return _dataStrings + End Get + End Property + + Public Sub New(fileName As String) + _datName = Path.GetFileNameWithoutExtension(fileName) + Dim fileBytes = File.ReadAllBytes(fileName) + ParseDatFile(New MemoryStream(fileBytes)) + End Sub + + Public Sub New(inStream As Stream, fileName As String) + _datName = Path.GetFileNameWithoutExtension(fileName) + ParseDatFile(inStream) + End Sub + + Private Sub ParseDatFile(inStream As Stream) + Try + _dat = New DatContainer(inStream, _datName) + Dim containerData = DataEntries.ToList() + Dim userStringOffsets = _dat.GetUserStringOffsets() + For Each keyValuePair In containerData + Dim data = keyValuePair.Value + Dim isUser = userStringOffsets.Contains(keyValuePair.Key) + Strings.Add(New DatString(data, isUser)) + Next + Catch ex As Exception + Throw New Exception(String.Format("Failed to read dat: {0}", ex.Message), ex) + End Try + End Sub + + Public Sub Save(savePath As String) + Try + _dat.Save(savePath) + Catch ex As Exception + Dim errorString As New StringBuilder() + Dim temp = ex + While (temp IsNot Nothing) + errorString.AppendLine(temp.Message) + temp = temp.InnerException + End While + MessageBox.Show(String.Format("Failed to save: {0}", errorString), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + End Try + MessageBox.Show(String.Format("Saved '{0}'", savePath), "Saved", MessageBoxButtons.OK, MessageBoxIcon.Information) + End Sub + + Public Function GetCSV() As String + Return _dat.GetCsvFormat() + End Function + + End Class +End Namespace \ No newline at end of file diff --git a/DatEditer/Form1.Designer.vb b/DatEditer/Form1.Designer.vb new file mode 100644 index 0000000..5602d3b --- /dev/null +++ b/DatEditer/Form1.Designer.vb @@ -0,0 +1,114 @@ + _ +Partial Class Form1 + Inherits System.Windows.Forms.Form + + 'Form 覆寫 Dispose 以清除元件清單。 + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + '為 Windows Form 設計工具的必要項 + Private components As System.ComponentModel.IContainer + + '注意: 以下為 Windows Form 設計工具所需的程序 + '可以使用 Windows Form 設計工具進行修改。 + '請勿使用程式碼編輯器進行修改。 + _ + Private Sub InitializeComponent() + Me.Button1 = New System.Windows.Forms.Button() + Me.TextBox1 = New System.Windows.Forms.TextBox() + Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog() + Me.DataGridView1 = New System.Windows.Forms.DataGridView() + Me.Button2 = New System.Windows.Forms.Button() + Me.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog() + CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).BeginInit() + Me.SuspendLayout() + ' + 'Button1 + ' + Me.Button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.Button1.Location = New System.Drawing.Point(862, 0) + Me.Button1.Name = "Button1" + Me.Button1.Size = New System.Drawing.Size(138, 29) + Me.Button1.TabIndex = 0 + Me.Button1.Text = "Select .Dat File" + Me.Button1.UseVisualStyleBackColor = True + ' + 'TextBox1 + ' + Me.TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ + Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.TextBox1.Location = New System.Drawing.Point(0, 0) + Me.TextBox1.Name = "TextBox1" + Me.TextBox1.ReadOnly = True + Me.TextBox1.Size = New System.Drawing.Size(862, 29) + Me.TextBox1.TabIndex = 1 + ' + 'OpenFileDialog1 + ' + Me.OpenFileDialog1.DefaultExt = "dat" + Me.OpenFileDialog1.Filter = "POE Dat File|*.dat" + ' + 'DataGridView1 + ' + Me.DataGridView1.AllowUserToDeleteRows = False + Me.DataGridView1.AllowUserToOrderColumns = True + Me.DataGridView1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _ + Or System.Windows.Forms.AnchorStyles.Left) _ + Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize + Me.DataGridView1.Location = New System.Drawing.Point(0, 30) + Me.DataGridView1.Name = "DataGridView1" + Me.DataGridView1.RowTemplate.Height = 24 + Me.DataGridView1.Size = New System.Drawing.Size(1143, 608) + Me.DataGridView1.TabIndex = 2 + ' + 'Button2 + ' + Me.Button2.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.Button2.Enabled = False + Me.Button2.Location = New System.Drawing.Point(999, 0) + Me.Button2.Name = "Button2" + Me.Button2.Size = New System.Drawing.Size(144, 29) + Me.Button2.TabIndex = 3 + Me.Button2.Text = "Apply Changes" + Me.Button2.UseVisualStyleBackColor = True + ' + 'SaveFileDialog1 + ' + Me.SaveFileDialog1.DefaultExt = "dat" + Me.SaveFileDialog1.Filter = "POE Dat File|*.dat|All Files|*.*" + ' + 'Form1 + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(10.0!, 20.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(1143, 638) + Me.Controls.Add(Me.Button2) + Me.Controls.Add(Me.DataGridView1) + Me.Controls.Add(Me.TextBox1) + Me.Controls.Add(Me.Button1) + Me.Font = New System.Drawing.Font("微軟正黑體", 12.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(136, Byte)) + Me.Margin = New System.Windows.Forms.Padding(5) + Me.Name = "Form1" + Me.Text = "DatEditer" + CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).EndInit() + Me.ResumeLayout(False) + Me.PerformLayout() + + End Sub + + Friend WithEvents Button1 As Button + Friend WithEvents TextBox1 As TextBox + Friend WithEvents OpenFileDialog1 As OpenFileDialog + Friend WithEvents DataGridView1 As DataGridView + Friend WithEvents Button2 As Button + Friend WithEvents SaveFileDialog1 As SaveFileDialog +End Class diff --git a/DatEditer/Form1.resx b/DatEditer/Form1.resx new file mode 100644 index 0000000..0f7a571 --- /dev/null +++ b/DatEditer/Form1.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 166, 17 + + \ No newline at end of file diff --git a/DatEditer/Form1.vb b/DatEditer/Form1.vb new file mode 100644 index 0000000..eaf69fd --- /dev/null +++ b/DatEditer/Form1.vb @@ -0,0 +1,28 @@ +Public Class Form1 + + Dim dat As VisualGGPK.DatWrapper + + Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click + + If (OpenFileDialog1.ShowDialog = DialogResult.OK) Then + + TextBox1.Text = OpenFileDialog1.FileName + dat = New VisualGGPK.DatWrapper(TextBox1.Text) + DataGridView1.DataSource = dat.Strings + Button2.Enabled = True + + End If + + End Sub + + Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click + + SaveFileDialog1.FileName = OpenFileDialog1.SafeFileName + If (SaveFileDialog1.ShowDialog = DialogResult.OK) Then + + dat.Save(SaveFileDialog1.FileName) + + End If + + End Sub +End Class \ No newline at end of file diff --git a/DatEditer/My Project/Application.Designer.vb b/DatEditer/My Project/Application.Designer.vb new file mode 100644 index 0000000..3b73525 --- /dev/null +++ b/DatEditer/My Project/Application.Designer.vb @@ -0,0 +1,38 @@ +'------------------------------------------------------------------------------ +' +' 這段程式碼是由工具產生的。 +' 執行階段版本:4.0.30319.42000 +' +' 對這個檔案所做的變更可能會造成錯誤的行為,而且如果重新產生程式碼, +' 變更將會遺失。 +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + '注意:這是自動產生的檔案,請勿直接修改它。若要進行變更, + ' 或者您在這個檔案發生建置錯誤,請到專案設計工具 + ' (移至專案屬性或者在 [方案總管] 中按兩下 [My Project] 節點), + ' 然後在 [應用程式] 索引標籤上進行變更。 + ' + Partial Friend Class MyApplication + + _ + Public Sub New() + MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows) + Me.IsSingleInstance = false + Me.EnableVisualStyles = true + Me.SaveMySettingsOnExit = false + Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses + End Sub + + _ + Protected Overrides Sub OnCreateMainForm() + Me.MainForm = Global.DatEditer.Form1 + End Sub + End Class +End Namespace diff --git a/DatEditer/My Project/Application.myapp b/DatEditer/My Project/Application.myapp new file mode 100644 index 0000000..3d33ef6 --- /dev/null +++ b/DatEditer/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + true + Form1 + false + 0 + true + 0 + false + \ No newline at end of file diff --git a/DatEditer/My Project/AssemblyInfo.vb b/DatEditer/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..8c0335f --- /dev/null +++ b/DatEditer/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' 組件的一般資訊是由下列的屬性集控制。 +' 變更這些屬性的值即可修改組件的相關 +' 資訊。 + +' 檢閱組件屬性的值 + + + + + + + + + + +'下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID + + +' 組件的版本資訊由下列四個值所組成: +' +' 主要版本 +' 次要版本 +' 組建編號 +' 修訂編號 +' +' 您可以指定所有的值,或將組建編號或修訂編號設為預設值 +' 指定為預設值: +' + + + diff --git a/DatEditer/My Project/Resources.Designer.vb b/DatEditer/My Project/Resources.Designer.vb new file mode 100644 index 0000000..1189319 --- /dev/null +++ b/DatEditer/My Project/Resources.Designer.vb @@ -0,0 +1,62 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("DatEditer.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set(ByVal value As Global.System.Globalization.CultureInfo) + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/DatEditer/My Project/Resources.resx b/DatEditer/My Project/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/DatEditer/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DatEditer/My Project/Settings.Designer.vb b/DatEditer/My Project/Settings.Designer.vb new file mode 100644 index 0000000..8ecbbf4 --- /dev/null +++ b/DatEditer/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.DatEditer.My.MySettings + Get + Return Global.DatEditer.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/DatEditer/My Project/Settings.settings b/DatEditer/My Project/Settings.settings new file mode 100644 index 0000000..377f56d --- /dev/null +++ b/DatEditer/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + From c98ce5662d24d807bb4ec9adc88f09ee17f7a58b Mon Sep 17 00:00:00 2001 From: aianlinb Date: Wed, 25 Dec 2019 20:02:30 +0800 Subject: [PATCH 2/3] Update PoeStrings Add "isUser" attribute to DatDefinitions.xml. This makes PoeStrings work properly. Add to PoeStrings.i18n.xml.Example. This allows PoeStrings to set up work folders for other Languages For example: Traditional Chinese --- LibDat/DatDefinitions.xml | 9436 +++++++++---------- PoeStrings/Backend.cs | 783 +- PoeStrings/MainWindow.xaml | 66 +- PoeStrings/MainWindow.xaml.cs | 400 +- PoeStrings/MainWindow.xaml.cs.bak | 200 + PoeStrings/Properties/Resources.Designer.cs | 495 +- PoeStrings/Properties/Resources.resx | 361 +- PoeStrings/StringEditor.xaml | 2 +- PoeStrings/StringEditor.xaml.cs | 243 +- 9 files changed, 6097 insertions(+), 5889 deletions(-) create mode 100644 PoeStrings/MainWindow.xaml.cs.bak diff --git a/LibDat/DatDefinitions.xml b/LibDat/DatDefinitions.xml index 224f4ba..be9fde9 100644 --- a/LibDat/DatDefinitions.xml +++ b/LibDat/DatDefinitions.xml @@ -1,4718 +1,4718 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PoeStrings/Backend.cs b/PoeStrings/Backend.cs index ae8ae61..55fe48b 100644 --- a/PoeStrings/Backend.cs +++ b/PoeStrings/Backend.cs @@ -1,394 +1,389 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using System.Xml.Serialization; -using LibDat; -using LibDat.Data; -using LibGGPK; -using LibGGPK.Records; -using PoeStrings.Properties; -using FieldInfo = System.Reflection.FieldInfo; - -namespace PoeStrings -{ - public class Backend - { - //private const string settingsPath = ".\\translation.xml"; - private readonly Action outputFunc; - private GrindingGearsPackageContainer content = new GrindingGearsPackageContainer(); - private string ggpkPath; - private string settingsPath; - - - /// - /// Maps file names to FileRecord - /// - private Dictionary fileRecordMap; - public Dictionary AllDatTranslations { get; set; } - - public Backend(Action outputFunc, string settingsPath) - { - this.settingsPath = settingsPath; - this.outputFunc = outputFunc; - } - - public void ReloadAllData(string ggpkPath) - { - this.ggpkPath = ggpkPath; - content = new GrindingGearsPackageContainer(); - content.Read(ggpkPath, outputFunc); - - CollectTranslatableStrings(); - MergeUserTranslations(); - } - - /// - /// Merges user translations with master list of transleatable strings and determiens if the user - /// translation is already applied or is invalid (possibly due to a patch). - /// - private void MergeUserTranslations() - { - Dictionary userDatTranslations; - try - { - userDatTranslations = ReadTranslationData(); - } - catch (Exception ex) - { - OutputLine(string.Format(Settings.Strings["ReloadAllData_Failed"], ex.Message)); - return; - } - - if (userDatTranslations == null) - { - return; - } - - foreach (var userTranslation in userDatTranslations) - { - if (!AllDatTranslations.ContainsKey(userTranslation.Key)) - { - AllDatTranslations.Add(userTranslation.Key, new DatTranslation()); - } - - var currentDatTranslation = AllDatTranslations[userTranslation.Key]; - - if (AllDatTranslations[userTranslation.Key].Translations == null) - continue; - - // Mapping of originalText -> Translation pairs to determine if the user translation is already applied, not yet applied, or no longer valid - var translationsByOriginalHash = AllDatTranslations[userTranslation.Key].Translations.ToDictionary(k => k.OriginalText); - - foreach (var translation in userTranslation.Value.Translations) - { - if (translationsByOriginalHash.ContainsKey(translation.OriginalText)) - { - translation.Status = Translation.TranslationStatus.NeedToApply; - - translationsByOriginalHash[translation.OriginalText].Status = translation.Status; - translationsByOriginalHash[translation.OriginalText].TranslatedText = translation.TranslatedText; - translationsByOriginalHash[translation.OriginalText].CurrentText = translation.OriginalText; - } - else if (translationsByOriginalHash.ContainsKey(translation.TranslatedText)) - { - translation.Status = Translation.TranslationStatus.AlreadyApplied; - - translationsByOriginalHash[translation.TranslatedText].Status = translation.Status; - translationsByOriginalHash[translation.TranslatedText].TranslatedText = translation.TranslatedText; - translationsByOriginalHash[translation.TranslatedText].CurrentText = translation.TranslatedText; - translationsByOriginalHash[translation.TranslatedText].OriginalText = translation.OriginalText; - } - else - { - translation.Status = Translation.TranslationStatus.Invalid; - currentDatTranslation.Translations.Add(translation); - } - } - } - } - - /// - /// Applies translations to content.ggpk - /// - 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' - datRecord.ReplaceContents(ggpkPath, dc.SaveAsBytes(), content.FreeRoot); - } - - if (outputBuffer.Length > 0) - { - Output(outputBuffer.ToString()); - } - } - - /// - /// Applies translations to content.ggpk - /// - 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()); - } - } - - /// - /// Searches all of the /data/*.dat files in content.ggpk for user strings that can be translated. Also fills - /// out 'fileRecordMap' with valid datName -> FileRecord mappings. - /// - private void CollectTranslatableStrings() - { - AllDatTranslations = new Dictionary(); - fileRecordMap = new Dictionary(); - - foreach (var recordOffset in content.RecordOffsets) - { - var record = recordOffset.Value as FileRecord; - - if (record == null || record.ContainingDirectory == null || record.DataLength == 12 || Path.GetExtension(record.Name) != ".dat") - continue; - - // Make sure parser for .dat type actually exists - if (!RecordFactory.HasRecordInfo(record.Name)) - continue; - - if (record.ContainingDirectory.Name != "Data") - continue; - - // We'll need this .dat FileRecord later on so we're storing it in a map of fileName -> FileRecord - fileRecordMap.Add(record.Name, record); - - List translatableStrings; - - try - { - translatableStrings = GetTranslatableStringsFromDatFile(record); - } - catch (Exception ex) - { - OutputLine(string.Format(Settings.Strings["CollectTranslatableStrings_FailedReading"], record.Name, ex.Message)); - continue; - } - - var newDatTranslation = new DatTranslation(); - newDatTranslation.DatName = record.Name; - newDatTranslation.Translations = new List(); - - foreach (var str in translatableStrings) - { - newDatTranslation.Translations.Add(new Translation(str)); - } - - if (translatableStrings.Count > 0) - { - AllDatTranslations.Add(record.Name, newDatTranslation); - } - } - } - - /// - /// Gets a list of all translatable strings in specified record. Record must be a FileRecord of a valid dat file. - /// - /// Dat File Record to extract translatable strings from - /// List of translatable strings contained in specified dat file - private List 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(); - - 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. - Where(s => !resultList.Contains(s.GetValueString()))) - { - resultList.Add(currentDatString.GetValueString()); - } - } - - return resultList.ToList(); - } - - /// - /// Saves all translations to file - /// - public void SaveTranslationData() - { - var debugTranslationCount = 0; - - var datTranslations = new List(); - var serializer = new XmlSerializer(datTranslations.GetType()); - using (var fs = new FileStream(settingsPath, FileMode.Create)) - { - foreach (var datTranslationTable in AllDatTranslations) - { - if (datTranslationTable.Value.Translations == null || datTranslationTable.Value.Translations.Count == 0) - continue; - - var newDatTranslation = new DatTranslation() - { - DatName = datTranslationTable.Key, - Translations = (from n in datTranslationTable.Value.Translations - where n.Status != Translation.TranslationStatus.Ignore - select - new Translation() - { - TranslatedText = n.TranslatedText.Replace(Environment.NewLine, "__BREAK__"), - OriginalText = n.OriginalText.Replace(Environment.NewLine, "__BREAK__"), - }).ToList() - }; - - if (newDatTranslation.Translations.Count > 0) - { - datTranslations.Add(newDatTranslation); - debugTranslationCount += newDatTranslation.Translations.Count; - } - } - - serializer.Serialize(fs, datTranslations); - OutputLine(String.Format(Settings.Strings["SaveTranslationData_Successful"], debugTranslationCount, settingsPath)); - } - } - - /// - /// Reads user translations from file - /// - /// - private Dictionary ReadTranslationData() - { - var debugTranslationCount = 0; - - var newUserTranslations = new Dictionary(); - - var serializer = new XmlSerializer(typeof(List)); - var deserializedTranslations = (List)serializer.Deserialize(XmlReader.Create(settingsPath)); - - foreach (var datTranslationTable in deserializedTranslations) - { - newUserTranslations.Add(datTranslationTable.DatName, datTranslationTable); - - foreach (var translation in datTranslationTable.Translations) - { - ++debugTranslationCount; - translation.TranslatedText = translation.TranslatedText.Replace("__BREAK__", Environment.NewLine); - translation.OriginalText = translation.OriginalText.Replace("__BREAK__", Environment.NewLine); - translation.Status = Translation.TranslationStatus.Invalid; - } - } - - OutputLine(string.Format(Settings.Strings["ReadTranslationData_Successful"], debugTranslationCount)); - return newUserTranslations; - } - - private void Output(string text) - { - if (outputFunc != null) - outputFunc(text); - } - - private void OutputLine(string text) - { - Output(text + Environment.NewLine); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Serialization; +using LibDat; +using LibDat.Data; +using LibGGPK; +using LibGGPK.Records; +using PoeStrings.Properties; +using FieldInfo = System.Reflection.FieldInfo; + +namespace PoeStrings +{ + public class Backend + { + //private const string settingsPath = ".\\translation.xml"; + private readonly Action outputFunc; + private GrindingGearsPackageContainer content = new GrindingGearsPackageContainer(); + private string ggpkPath; + private string settingsPath; + + + /// + /// Maps file names to FileRecord + /// + private Dictionary fileRecordMap; + public Dictionary AllDatTranslations { get; set; } + + public Backend(Action outputFunc, string settingsPath) + { + this.settingsPath = settingsPath; + this.outputFunc = outputFunc; + } + + public void ReloadAllData(string ggpkPath) + { + this.ggpkPath = ggpkPath; + content = new GrindingGearsPackageContainer(); + content.Read(ggpkPath, outputFunc); + + CollectTranslatableStrings(); + MergeUserTranslations(); + } + + /// + /// Merges user translations with master list of transleatable strings and determiens if the user + /// translation is already applied or is invalid (possibly due to a patch). + /// + private void MergeUserTranslations() + { + Dictionary userDatTranslations; + try + { + userDatTranslations = ReadTranslationData(); + } + catch (Exception ex) + { + OutputLine(string.Format(Settings.Strings["ReloadAllData_Failed"], ex.Message)); + return; + } + + if (userDatTranslations == null) + { + return; + } + + foreach (var userTranslation in userDatTranslations) + { + if (!AllDatTranslations.ContainsKey(userTranslation.Key)) + { + AllDatTranslations.Add(userTranslation.Key, new DatTranslation()); + } + + var currentDatTranslation = AllDatTranslations[userTranslation.Key]; + + if (AllDatTranslations[userTranslation.Key].Translations == null) + continue; + + // Mapping of originalText -> Translation pairs to determine if the user translation is already applied, not yet applied, or no longer valid + var translationsByOriginalHash = AllDatTranslations[userTranslation.Key].Translations.ToDictionary(k => k.OriginalText); + + foreach (var translation in userTranslation.Value.Translations) + { + if (translationsByOriginalHash.ContainsKey(translation.OriginalText)) + { + translation.Status = Translation.TranslationStatus.NeedToApply; + + translationsByOriginalHash[translation.OriginalText].Status = translation.Status; + translationsByOriginalHash[translation.OriginalText].TranslatedText = translation.TranslatedText; + translationsByOriginalHash[translation.OriginalText].CurrentText = translation.OriginalText; + } + else if (translationsByOriginalHash.ContainsKey(translation.TranslatedText)) + { + translation.Status = Translation.TranslationStatus.AlreadyApplied; + + translationsByOriginalHash[translation.TranslatedText].Status = translation.Status; + translationsByOriginalHash[translation.TranslatedText].TranslatedText = translation.TranslatedText; + translationsByOriginalHash[translation.TranslatedText].CurrentText = translation.TranslatedText; + translationsByOriginalHash[translation.TranslatedText].OriginalText = translation.OriginalText; + } + else + { + translation.Status = Translation.TranslationStatus.Invalid; + currentDatTranslation.Translations.Add(translation); + } + } + } + } + + /// + /// Applies translations to content.ggpk + /// + 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' + datRecord.ReplaceContents(ggpkPath, dc.SaveAsBytes(), content.FreeRoot); + } + + if (outputBuffer.Length > 0) + { + Output(outputBuffer.ToString()); + } + } + + /// + /// Applies translations to content.ggpk + /// + 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()); + } + } + + /// + /// Searches all of the /data/*.dat files in content.ggpk for user strings that can be translated. Also fills + /// out 'fileRecordMap' with valid datName -> FileRecord mappings. + /// + private void CollectTranslatableStrings() + { + AllDatTranslations = new Dictionary(); + fileRecordMap = new Dictionary(); + + foreach (var recordOffset in content.RecordOffsets) + { + var record = recordOffset.Value as FileRecord; + + if (record == null || record.ContainingDirectory == null || record.DataLength == 12 || Path.GetExtension(record.Name) != ".dat") + continue; + + // Make sure parser for .dat type actually exists + if (!RecordFactory.HasRecordInfo(record.Name)) + continue; + + if (record.ContainingDirectory.Name != Settings.Strings["Path"]) + continue; + + // We'll need this .dat FileRecord later on so we're storing it in a map of fileName -> FileRecord + fileRecordMap.Add(record.Name, record); + + List translatableStrings; + + try + { + translatableStrings = GetTranslatableStringsFromDatFile(record); + } + catch (Exception ex) + { + OutputLine(string.Format(Settings.Strings["CollectTranslatableStrings_FailedReading"], record.Name, ex.Message)); + continue; + } + + var newDatTranslation = new DatTranslation(record.Name); + + foreach (var str in translatableStrings) + { + newDatTranslation.Translations.Add(new Translation(str)); + } + + + if (translatableStrings.Count > 0) + { + AllDatTranslations.Add(record.Name, newDatTranslation); + } + } + } + + /// + /// Gets a list of all translatable strings in specified record. Record must be a FileRecord of a valid dat file. + /// + /// Dat File Record to extract translatable strings from + /// List of translatable strings contained in specified dat file + private List 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(); + 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(); + } + + /// + /// Saves all translations to file + /// + public void SaveTranslationData() + { + var debugTranslationCount = 0; + + var datTranslations = new List(); + var serializer = new XmlSerializer(datTranslations.GetType()); + using (var fs = new FileStream(settingsPath, FileMode.Create)) + { + foreach (var datTranslationTable in AllDatTranslations) + { + if (datTranslationTable.Value.Translations == null || datTranslationTable.Value.Translations.Count == 0) + continue; + + var newDatTranslation = new DatTranslation() + { + DatName = datTranslationTable.Key, + Translations = (from n in datTranslationTable.Value.Translations + where n.Status != Translation.TranslationStatus.Ignore + select + new Translation() + { + TranslatedText = n.TranslatedText.Replace(Environment.NewLine, "__BREAK__"), + OriginalText = n.OriginalText.Replace(Environment.NewLine, "__BREAK__"), + }).ToList() + }; + + if (newDatTranslation.Translations.Count > 0) + { + datTranslations.Add(newDatTranslation); + debugTranslationCount += newDatTranslation.Translations.Count; + } + } + + serializer.Serialize(fs, datTranslations); + OutputLine(String.Format(Settings.Strings["SaveTranslationData_Successful"], debugTranslationCount, settingsPath)); + } + } + + /// + /// Reads user translations from file + /// + /// + private Dictionary ReadTranslationData() + { + var debugTranslationCount = 0; + + var newUserTranslations = new Dictionary(); + + var serializer = new XmlSerializer(typeof(List)); + var deserializedTranslations = (List)serializer.Deserialize(XmlReader.Create(settingsPath)); + + foreach (var datTranslationTable in deserializedTranslations) + { + newUserTranslations.Add(datTranslationTable.DatName, datTranslationTable); + + foreach (var translation in datTranslationTable.Translations) + { + ++debugTranslationCount; + translation.TranslatedText = translation.TranslatedText.Replace("__BREAK__", Environment.NewLine); + translation.OriginalText = translation.OriginalText.Replace("__BREAK__", Environment.NewLine); + translation.Status = Translation.TranslationStatus.Invalid; + } + } + + OutputLine(string.Format(Settings.Strings["ReadTranslationData_Successful"], debugTranslationCount)); + return newUserTranslations; + } + + private void Output(string text) + { + if (outputFunc != null) + outputFunc(text); + } + + private void OutputLine(string text) + { + Output(text + Environment.NewLine); + } + } +} diff --git a/PoeStrings/MainWindow.xaml b/PoeStrings/MainWindow.xaml index 17a4153..e8bce06 100644 --- a/PoeStrings/MainWindow.xaml +++ b/PoeStrings/MainWindow.xaml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - -