From 13856a0960645fab34a900f32b000b5d5e99a56b Mon Sep 17 00:00:00 2001
From: 1cekrim <1cekrim.dev@gmail.com>
Date: Sun, 15 May 2022 13:19:15 +0900
Subject: [PATCH] 1.1
---
stellaris_mod_lang_patcher/MainWindow.xaml | 68 ++--
stellaris_mod_lang_patcher/MainWindow.xaml.cs | 323 ++++++++++++++++--
.../stellaris_mod_lang_patcher.csproj | 4 +
3 files changed, 337 insertions(+), 58 deletions(-)
diff --git a/stellaris_mod_lang_patcher/MainWindow.xaml b/stellaris_mod_lang_patcher/MainWindow.xaml
index 0647c0e..a4da55a 100644
--- a/stellaris_mod_lang_patcher/MainWindow.xaml
+++ b/stellaris_mod_lang_patcher/MainWindow.xaml
@@ -5,39 +5,41 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:stellaris_mod_lang_patcher"
mc:Ignorable="d"
- Title="Stellaris Mod Language Patcher" Height="850" Width="600">
+ Title="Stellaris Mod Language Patcher" Height="600" Width="800">
-
-
-
- C:\Program Files (x86)\Steam\steamapps\workshop\content\281990
-
-
-
-
-
-
-
-
- english
-
- korean
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ C:\Program Files (x86)\Steam\steamapps\workshop\content\281990
+
+
+
+
+
+
+
+
+ english
+
+ korean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/stellaris_mod_lang_patcher/MainWindow.xaml.cs b/stellaris_mod_lang_patcher/MainWindow.xaml.cs
index 11fdf07..b9c18e0 100644
--- a/stellaris_mod_lang_patcher/MainWindow.xaml.cs
+++ b/stellaris_mod_lang_patcher/MainWindow.xaml.cs
@@ -21,10 +21,86 @@ public partial class MainWindow : Window
{
string mod_folder_path = @"C:\Program Files (x86)\Steam\steamapps\workshop\content\281990";
List mods = null;
+ private enum ProgramState { INVALID, IDLE, RUNNING, ERROR }
+ ProgramState current_state = ProgramState.IDLE;
+ object state_lock = new object();
+
+ Dictionary> force_patch_dict = new Dictionary> {
+ { "korean", new List {
+ "2703186360", // MKC Addon: AlphaMod
+ "2524944243", // MKC Addon: Gigastructural Engineering & More
+ "2420144001", // MKC Addon : Planetary Diversity Korean Translation
+ "2524947989", // MKC Addon: NSC2 Season 6
+ "2533584571", // MKC Addon: Ethics and Civics Alternative - Redux
+ "2789326040", // MKC Addon: Real Space - New Frontiers
+ "2547749868", // MKC Addon: Ethics and Civics Classic 3.0
+ "2703189043", // MKC Addon: EUTAB - Ethos Unique Techs and Buildings
+ "2506141839", // Mod Korean Collection: 모드 한국어 모음
+ "2747894657", // Korean Language(Korean name)
+ } }
+ };
+
+ Dictionary file_name_typo_dict = new Dictionary
+ {
+ { "l_koean", "l_korean" }
+ };
+
+ private bool ChangeState(ProgramState next_state, ProgramState condition = ProgramState.INVALID)
+ {
+ lock (state_lock)
+ {
+ if (condition != ProgramState.INVALID && condition != current_state)
+ {
+ return false;
+ }
+
+ current_state = next_state;
+
+
+ Dispatcher.Invoke(() =>
+ {
+ switch (current_state)
+ {
+ case ProgramState.IDLE:
+ Title = "Stellaris Mod Language Patcher - Idle";
+ Button_LoadModList.IsEnabled = true;
+ Button_Patch.IsEnabled = mods != null;
+ TextBox_From.IsEnabled = true;
+ TextBox_To.IsEnabled = true;
+ TextBox_Mod_Folder.IsEnabled = true;
+ break;
+ case ProgramState.RUNNING:
+ Title = "Stellaris Mod Language Patcher - Running";
+ Button_LoadModList.IsEnabled = false;
+ Button_Patch.IsEnabled = false;
+ TextBox_From.IsEnabled = false;
+ TextBox_To.IsEnabled = false;
+ TextBox_Mod_Folder.IsEnabled = false;
+ break;
+ case ProgramState.ERROR:
+ Title = "Stellaris Mod Language Patcher - Error";
+ Button_LoadModList.IsEnabled = false;
+ Button_Patch.IsEnabled = false;
+ TextBox_From.IsEnabled = false;
+ TextBox_To.IsEnabled = false;
+ TextBox_Mod_Folder.IsEnabled = false;
+ break;
+ }
+ });
+
+ return true;
+ }
+ }
+
public MainWindow()
{
InitializeComponent();
+ ChangeState(ProgramState.RUNNING);
TextBox_Mod_Folder.Text = mod_folder_path;
+
+ DataGridTextColumn_From.Header = "Support " + TextBox_From.Text;
+ DataGridTextColumn_To.Header = "Support " + TextBox_To.Text;
+ ChangeState(ProgramState.IDLE);
}
public List LoadModList(string path, string from, string to)
@@ -51,19 +127,20 @@ public List LoadModList(string path, string from, string to)
string[]? splited = line?.Split("=");
if (splited?.Length >= 2 && splited[0].Trim() == "name")
{
- mod.Name = "(" + mod.Code + ")\t" + splited[1].Trim().Trim('"');
+ mod.Name = splited[1].Trim().Trim('"');
}
}
}
var localisation_folder = new DirectoryInfo(System.IO.Path.Join(mod_folder.FullName, "localisation"));
- if (!localisation_folder.Exists)
+ var localisation_synced_folder = new DirectoryInfo(System.IO.Path.Join(mod_folder.FullName, "localisation_synced"));
+ if (!localisation_folder.Exists && !localisation_synced_folder.Exists)
{
continue;
}
var from_folder = new DirectoryInfo(System.IO.Path.Join(localisation_folder.FullName, from));
mod.HasFrom = from_folder.Exists;
-
+
var to_folder = new DirectoryInfo(System.IO.Path.Join(localisation_folder.FullName, to));
mod.HasTo = to_folder.Exists;
@@ -93,27 +170,40 @@ public List LoadModList(string path, string from, string to)
continue;
}
- if (mod.HasFrom && !mod.HasTo)
- {
- mod_list.Add(mod);
- }
+ mod_list.Add(mod);
}
return mod_list;
}
- private void Button_LoadModList_Click(object sender, RoutedEventArgs e)
+ private async void Button_LoadModList_Click(object sender, RoutedEventArgs e)
+ {
+ if (!ChangeState(ProgramState.RUNNING, ProgramState.IDLE))
+ {
+ return;
+ }
+ await UpdateModList();
+ ChangeState(ProgramState.IDLE);
+ }
+
+ private async Task UpdateModList()
{
try
{
mod_folder_path = TextBox_Mod_Folder.Text;
+
string from = TextBox_From.Text;
string to = TextBox_To.Text;
- var mod_list = LoadModList(mod_folder_path, from, to);
+ var mod_list = await Task.Run(() =>
+ {
+ return LoadModList(mod_folder_path, from, to);
+ });
- DataContext = mod_list;
+ DataGridTextColumn_From.Header = "Support " + TextBox_From.Text;
+ DataGridTextColumn_To.Header = "Support " + TextBox_To.Text;
+ Mod_List.DataContext = mod_list;
mods = mod_list;
}
catch (Exception ex)
@@ -121,6 +211,7 @@ private void Button_LoadModList_Click(object sender, RoutedEventArgs e)
MessageBox.Show(ex.Message);
}
}
+
private void CopyFolder(string src, string dist)
{
foreach (string dirPath in Directory.GetDirectories(src, "*", SearchOption.AllDirectories))
@@ -129,12 +220,17 @@ private void CopyFolder(string src, string dist)
}
foreach (string newPath in Directory.GetFiles(src, "*.*", SearchOption.AllDirectories))
{
- File.Copy(newPath, newPath.Replace(src, dist), true);
+ File.Copy(newPath, newPath.Replace(src, dist), false);
}
}
- private void Button_Patch_Click(object sender, RoutedEventArgs e)
+ private async void Button_Patch_Click(object sender, RoutedEventArgs e)
{
+ if (!ChangeState(ProgramState.RUNNING, ProgramState.IDLE))
+ {
+ return;
+ }
+
try
{
if (mods == null)
@@ -142,22 +238,79 @@ private void Button_Patch_Click(object sender, RoutedEventArgs e)
return;
}
- string from = TextBox_From.Text;
- string to = TextBox_To.Text;
+ await PatchMods(mods);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ ChangeState(ProgramState.ERROR);
+ return;
+ }
- string l_from = "l_" + from;
- string l_to = "l_" + to;
+ await UpdateModList();
+ ChangeState(ProgramState.IDLE);
+ MessageBox.Show("Done");
+ }
- foreach (var mod in mods)
+ public async Task PatchMods(List mods)
+ {
+ string from = TextBox_From.Text;
+ string to = TextBox_To.Text;
+
+ string l_from = "l_" + from;
+ string l_to = "l_" + to;
+
+ await Parallel.ForEachAsync(mods, async (mod, token) =>
+ {
+ await Task.Run(() =>
{
- // from 폴더를 to 폴더로 복사
+ // 파일명에 오타 있는 경우 수정
+ {
+ Queue q = new Queue();
+ if (mod.Folder == null)
+ {
+ return;
+ }
+
+ q.Enqueue(mod.Folder);
+ while (q.Count > 0)
+ {
+ var root = q.Dequeue();
+
+ foreach (var file in root.GetFiles())
+ {
+ foreach (var typo in file_name_typo_dict.Keys)
+ {
+ if (file.Name.Contains(typo))
+ {
+ string new_file_path = System.IO.Path.Join(root.FullName, file.Name.Replace(typo, file_name_typo_dict[typo]));
+ var new_file = new FileInfo(new_file_path);
+
+ if (new_file.Exists)
+ {
+ continue;
+ }
+
+ File.Move(file.FullName, new_file.FullName);
+ }
+ }
+ }
+
+ foreach (var dir in root.GetDirectories())
+ {
+ q.Enqueue(dir);
+ }
+ }
+ }
+
+ // from 폴더에 있는 파일들을 to 폴더로 복사
List from_folders = new List();
List to_folders = new List();
{
Queue q = new Queue();
if (mod.Folder == null)
{
- continue;
+ return;
}
q.Enqueue(mod.Folder);
@@ -195,7 +348,7 @@ private void Button_Patch_Click(object sender, RoutedEventArgs e)
Queue q = new Queue();
if (mod.Folder == null)
{
- continue;
+ return;
}
q.Enqueue(mod.Folder);
@@ -213,7 +366,7 @@ private void Button_Patch_Click(object sender, RoutedEventArgs e)
if (file.Name.Contains(l_from))
{
string new_file_path = System.IO.Path.Join(root.FullName, file.Name.Replace(from, to));
- var new_file = new DirectoryInfo(new_file_path);
+ var new_file = new FileInfo(new_file_path);
if (new_file.Exists)
{
continue;
@@ -244,7 +397,7 @@ private void Button_Patch_Click(object sender, RoutedEventArgs e)
if (file.Name.Contains(l_from))
{
string new_file_path = System.IO.Path.Join(to_folder.FullName, file.Name.Replace(from, to));
- var new_file = new DirectoryInfo(new_file_path);
+ var new_file = new FileInfo(new_file_path);
if (new_file.Exists)
{
continue;
@@ -260,12 +413,132 @@ private void Button_Patch_Click(object sender, RoutedEventArgs e)
}
}
}
+ });
+ });
+
+ // 기존 번역 모드들을 수정함
+ {
+ UpdateRegacyTranslationMods(mod_folder_path, from, to);
+ }
+
+ // 한글 이름 모드를 수정함
+ {
+ foreach (var mod in mods)
+ {
+ if (mod.Code == "2747894657")
+ {
+ string localisation_synced_path = System.IO.Path.Join(mod.Folder.FullName, "localisation_synced");
+ var localisation_synced = new DirectoryInfo(localisation_synced_path);
+ foreach (var file in localisation_synced.GetFiles())
+ {
+ bool is_first = true;
+ string file_text = File.ReadAllText(file.FullName);
+ StringReader reader = new StringReader(file_text);
+ string result = "";
+ while (true)
+ {
+ string? line = reader.ReadLine();
+ if (line == null)
+ {
+ break;
+ }
+
+ if (line.Contains(":") && is_first)
+ {
+ result += line + "\n";
+ is_first = false;
+ continue;
+ }
+
+ result += line.Replace(": ", ":0 ") + "\n";
+ }
+
+ File.WriteAllText(file.FullName, result, new UTF8Encoding(true));
+ }
+ }
}
- MessageBox.Show("Done");
+
}
- catch (Exception ex)
+ }
+
+ public void UpdateRegacyTranslationMods(string path, string from, string to)
+ {
+ DirectoryInfo di = new DirectoryInfo(path);
+
+ var mod_folders = di.GetDirectories();
+
+ string l_from = "l_" + from;
+ string l_to = "l_" + to;
+ foreach (var mod_folder in mod_folders)
{
- MessageBox.Show(ex.Message);
+ bool is_regacy = force_patch_dict.ContainsKey(to) && force_patch_dict[to].Contains(mod_folder.Name);
+ if (!is_regacy)
+ {
+ continue;
+ }
+
+ try
+ {
+ Queue q = new Queue();
+ q.Enqueue(mod_folder);
+ while (q.Count > 0)
+ {
+ var root = q.Dequeue();
+
+ foreach (var file in root.GetFiles())
+ {
+ if (file.Name.Contains(l_to))
+ {
+ string t = File.ReadAllText(file.FullName);
+ t = t.Replace(l_from, l_to);
+ File.WriteAllText(file.FullName, t, new UTF8Encoding(true));
+ }
+ }
+
+ foreach (var dir in root.GetDirectories())
+ {
+ q.Enqueue(dir);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ continue;
+ }
+
+ try
+ {
+ var localisation_folder = new DirectoryInfo(System.IO.Path.Join(mod_folder.FullName, "localisation"));
+ if (!localisation_folder.Exists)
+ {
+ continue;
+ }
+
+ var korean_folder = new DirectoryInfo(System.IO.Path.Join(localisation_folder.FullName, "korean"));
+ if (!korean_folder.Exists)
+ {
+ korean_folder.Create();
+ }
+
+ foreach (var file in localisation_folder.GetFiles())
+ {
+ if (file.Name.Contains(l_to))
+ {
+ var new_file_path = System.IO.Path.Join(korean_folder.FullName, file.Name);
+ var new_file = new FileInfo(new_file_path);
+ if (new_file.Exists)
+ {
+ continue;
+ }
+
+ File.Copy(file.FullName, new_file.FullName);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ continue;
+ }
}
}
}
diff --git a/stellaris_mod_lang_patcher/stellaris_mod_lang_patcher.csproj b/stellaris_mod_lang_patcher/stellaris_mod_lang_patcher.csproj
index 4106cb0..b1fa445 100644
--- a/stellaris_mod_lang_patcher/stellaris_mod_lang_patcher.csproj
+++ b/stellaris_mod_lang_patcher/stellaris_mod_lang_patcher.csproj
@@ -5,6 +5,10 @@
net6.0-windows
enable
true
+ stellaris_mod_lang_patcher.App
+ 1.1.0.0
+ 1.1.0.0
+ 1.1.0