Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of IntegratedKoreanPatch v1.7.1
IntegratedKoreanPatch/IntegratedKoreanPatch.dll
Decompiled 6 days agousing System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace IntegratedKoreanPatch; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("rexmods.integratedkoreanpatch", "통합한글패치", "1.7.1")] public sealed class Plugin : BaseUnityPlugin { private sealed class BoundText { public object Target; public FieldInfo Field; public string Original; public string Token; } private const string Guid = "rexmods.integratedkoreanpatch"; private static Plugin self; private Harmony harmony; private Action<Localization, string, string> addWord; private FieldInfo cacheField; private FieldInfo singletonField; private MethodInfo evictCache; private bool pending; private readonly Dictionary<string, string> cuisine = new Dictionary<string, string>(StringComparer.Ordinal); private int lastCuisineCount = -1; private readonly Dictionary<string, string> monstrum = new Dictionary<string, string>(StringComparer.Ordinal); private int lastMonstrumCount = -1; private bool warfareActive; private bool southsilActive; private string mainLanguage; private int lastWarfareCount = -1; private int lastSouthsilCount = -1; private bool bindingWarning; private readonly Dictionary<string, string> warfare = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<string, string[]> southsil = new Dictionary<string, string[]>(StringComparer.Ordinal); private readonly Dictionary<string, string> southsilWords = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<string, string> southsilEnglish = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<string, string[]> effects = new Dictionary<string, string[]>(StringComparer.Ordinal); private readonly Dictionary<string, string> setNames = new Dictionary<string, string>(StringComparer.Ordinal); private readonly HashSet<SharedData> ownedItems = new HashSet<SharedData>(); private readonly List<BoundText> boundTexts = new List<BoundText>(); private void Awake() { //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown self = this; MethodInfo method = typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(string) }, null); if (method == null || method.ReturnType != typeof(void)) { throw new MissingMethodException("Localization.AddWord(string,string)"); } addWord = (Action<Localization, string, string>)Delegate.CreateDelegate(typeof(Action<Localization, string, string>), method); cacheField = typeof(Localization).GetField("m_cache", BindingFlags.Instance | BindingFlags.NonPublic); if (cacheField == null) { throw new MissingFieldException("Localization.m_cache"); } singletonField = typeof(Localization).GetField("m_instance", BindingFlags.Static | BindingFlags.NonPublic); if (singletonField == null) { throw new MissingFieldException("Localization.m_instance"); } evictCache = cacheField.FieldType.GetMethod("EvictAll", Type.EmptyTypes); if (evictCache == null) { throw new MissingMethodException("Localization cache EvictAll"); } string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Data"); LoadData(Path.Combine(path, "Monstrum.tsv"), 2, monstrum, null); LoadData(Path.Combine(path, "Warfare.tsv"), 2, warfare, null); LoadData(Path.Combine(path, "ValheimCuisine.tsv"), 2, cuisine, null); LoadData(Path.Combine(path, "SouthsilArmor.tsv"), 5, null, southsil); LoadData(Path.Combine(path, "SouthsilEffects.tsv"), 5, null, effects); LoadData(Path.Combine(path, "SouthsilSets.tsv"), 2, setNames, null); harmony = new Harmony("rexmods.integratedkoreanpatch"); Install(typeof(Localization), "SetupLanguage", new Type[1] { typeof(string) }, "LanguageReady"); Install(typeof(ObjectDB), "Awake", Type.EmptyTypes, "DatabaseReady"); Install(typeof(ObjectDB), "CopyOtherDB", new Type[1] { typeof(ObjectDB) }, "DatabaseReady"); Install(typeof(ZNetScene), "Awake", Type.EmptyTypes, "DatabaseReady"); Install(typeof(ItemData), "GetTooltip", new Type[6] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) }, "ItemTooltipReady"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"통합한글패치 1.7.1: Warfare / SouthsilArmor / ValheimCuisine / Monstrum 번역."); } private void LoadData(string path, int columns, Dictionary<string, string> words, Dictionary<string, string[]> records) { try { Dictionary<string, string[]> dictionary = ParseData(File.ReadAllLines(ResolveTranslationPath(path), Encoding.ASCII), columns); foreach (KeyValuePair<string, string[]> item in dictionary) { words?.Add(item.Key, item.Value[1]); records?.Add(item.Key, item.Value); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)(Path.GetFileName(path) + " 번역 읽기 실패: " + ex.Message)); } } internal static string ResolveTranslationPath(string expectedPath) { if (File.Exists(expectedPath)) { return expectedPath; } string directoryName = Path.GetDirectoryName(Path.GetDirectoryName(expectedPath)); string text = Path.Combine(directoryName, Path.GetFileName(expectedPath)); if (File.Exists(text)) { return text; } throw new FileNotFoundException("Translation file not found in Data or plugin directory: " + Path.GetFileName(expectedPath), expectedPath); } internal static Dictionary<string, string[]> ParseData(string[] lines, int columns) { Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>(StringComparer.Ordinal); foreach (string text in lines) { if (!string.IsNullOrWhiteSpace(text)) { string[] array = text.Split(new char[1] { '\t' }, StringSplitOptions.None); if (array.Length != columns) { throw new InvalidDataException("잘못된 번역 열 개수"); } for (int j = 0; j < array.Length; j++) { array[j] = Encoding.UTF8.GetString(Convert.FromBase64String(array[j])); } if (string.IsNullOrEmpty(array[0]) || dictionary.ContainsKey(array[0])) { throw new InvalidDataException("비어 있거나 중복된 번역 키: " + array[0]); } dictionary.Add(array[0], array); } } return dictionary; } private void Install(Type type, string name, Type[] parameters, string handler) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null); if (method == null) { throw new MissingMethodException(type.FullName, name); } HarmonyMethod val = new HarmonyMethod(typeof(Plugin).GetMethod(handler, BindingFlags.Static | BindingFlags.NonPublic)); val.priority = 0; val.after = new string[1] { "shudnal.MyLittleUI" }; harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private IEnumerator Start() { yield return null; Refresh(); } private static void LanguageReady(Localization __instance, string __0) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown if (!((Object)self == (Object)null)) { self.Apply(__instance, __0); if (object.ReferenceEquals(__instance, self.singletonField.GetValue(null))) { self.mainLanguage = __0; self.QueueRefresh(); } } } private static void DatabaseReady() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown if ((Object)self != (Object)null) { self.QueueRefresh(); } } private void QueueRefresh() { if (!pending && ((Behaviour)this).isActiveAndEnabled) { pending = true; ((MonoBehaviour)this).StartCoroutine(RefreshNextFrame()); } } private IEnumerator RefreshNextFrame() { yield return null; pending = false; Refresh(); } private void Refresh() { Localization instance = Localization.instance; if (instance != null) { Apply(instance, mainLanguage ?? instance.GetSelectedLanguage()); } } private static bool IsLoaded(string guid) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Chainloader.PluginInfos.TryGetValue(guid, out var value) && value != null) { return (Object)value.Instance != (Object)null; } return false; } internal static bool ShouldApplyMonstrum(bool loaded, string language) { if (loaded) { return string.Equals(language, "Korean", StringComparison.Ordinal); } return false; } private void Apply(Localization localization, string language) { if (localization == null) { return; } bool flag = string.Equals(language, "Korean", StringComparison.Ordinal); warfareActive = IsLoaded("Therzie.Warfare"); southsilActive = IsLoaded("southsil.SouthsilArmor"); bool flag2 = IsLoaded("Therzie.Monstrum"); if (ShouldApplyMonstrum(flag2, language)) { foreach (KeyValuePair<string, string> item in monstrum) { addWord(localization, item.Key, item.Value); } if (lastMonstrumCount != monstrum.Count) { lastMonstrumCount = monstrum.Count; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Monstrum 한글 번역 적용: " + monstrum.Count + "개")); } } bool flag3 = IsLoaded("XutzBR.ValheimCuisine"); if (flag3 && flag) { foreach (KeyValuePair<string, string> item2 in cuisine) { addWord(localization, item2.Key, item2.Value); } if (lastCuisineCount != cuisine.Count) { lastCuisineCount = cuisine.Count; ((BaseUnityPlugin)this).Logger.LogInfo((object)("ValheimCuisine 한글 보완 적용: " + cuisine.Count + "개")); } } if (warfareActive && flag) { foreach (KeyValuePair<string, string> item3 in warfare) { addWord(localization, item3.Key, item3.Value); } if (lastWarfareCount != warfare.Count) { lastWarfareCount = warfare.Count; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Warfare 한글 번역 적용: " + warfare.Count + "개")); } } if (southsilActive) { BindSouthsilKeys(); foreach (KeyValuePair<string, string> item4 in flag ? southsilWords : southsilEnglish) { addWord(localization, item4.Key, localization.Localize(item4.Value)); } if (lastSouthsilCount != southsilWords.Count) { lastSouthsilCount = southsilWords.Count; ((BaseUnityPlugin)this).Logger.LogInfo((object)("SouthsilArmor 번역 키 등록: " + southsilWords.Count + "개 (장비 " + southsil.Count + "종, 효과 " + effects.Count + "종, 세트명 " + setNames.Count + "개)")); } } if (warfareActive || southsilActive || (flag3 && flag) || (flag2 && flag)) { evictCache.Invoke(cacheField.GetValue(localization), null); } } private void BindSouthsilKeys() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown try { if (!Chainloader.PluginInfos.TryGetValue("southsil.SouthsilArmor", out var value) || (Object)value.Instance == (Object)null) { return; } Type type = ((object)value.Instance).GetType().Assembly.GetType("ItemManager.Item", throwOnError: true); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = type.GetField("registeredItems", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("Prefab", bindingAttr); if (field == null || field2 == null) { throw new MissingFieldException("Southsil ItemManager binding"); } if (!(field.GetValue(null) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { object value2 = field2.GetValue(item); GameObject val = (GameObject)((value2 is GameObject) ? value2 : null); if (!((Object)val == (Object)null) && southsil.TryGetValue(((Object)val).name, out var value3)) { ItemDrop component = val.GetComponent<ItemDrop>(); if (!((Object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null) { SharedData shared = component.m_itemData.m_shared; ownedItems.Add(shared); BindText(shared, "m_name", "rex_ikp_item_" + ((Object)val).name + "_name", value3[1], value3[2]); BindText(shared, "m_description", "rex_ikp_item_" + ((Object)val).name + "_desc", value3[3], value3[4]); BindEffect(shared.m_setStatusEffect); BindEffect(shared.m_equipStatusEffect); } } } } catch (Exception ex) { if (!bindingWarning) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Southsil 번역 연결 실패: " + ex.Message)); } bindingWarning = true; } } private void BindText(object target, string fieldName, string key, string english, string korean) { if (target == null) { return; } FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != typeof(string)) { throw new MissingFieldException(fieldName); } string text = "$" + key; southsilWords[key] = korean; southsilEnglish[key] = english; foreach (BoundText boundText in boundTexts) { if (object.ReferenceEquals(boundText.Target, target) && boundText.Field.Name == fieldName) { field.SetValue(target, text); return; } } boundTexts.Add(new BoundText { Target = target, Field = field, Original = (field.GetValue(target) as string), Token = text }); field.SetValue(target, text); } private void BindEffect(StatusEffect effect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if (!((Object)effect == (Object)null) && effects.TryGetValue(((Object)effect).name, out var value)) { string text = "rex_ikp_effect_" + ((Object)effect).name.Replace(" ", "_"); BindText(effect, "m_name", text + "_name", value[1], value[2]); BindText(effect, "m_tooltip", text + "_desc", value[3], value[4]); } } private static void ItemTooltipReady(ItemData __0, ref string __result) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown if (!((Object)self == (Object)null) && __0 != null && __0.m_shared != null && !string.IsNullOrEmpty(__result) && self.ownedItems.Contains(__0.m_shared) && string.Equals(self.mainLanguage ?? Localization.instance.GetSelectedLanguage(), "Korean", StringComparison.Ordinal)) { string setName = __0.m_shared.m_setName; if (!string.IsNullOrEmpty(setName) && self.setNames.TryGetValue(setName, out var value)) { __result = __result.Replace(setName, value); } } } internal void RestoreTextBindings() { foreach (BoundText boundText in boundTexts) { if (string.Equals(boundText.Field.GetValue(boundText.Target) as string, boundText.Token, StringComparison.Ordinal)) { boundText.Field.SetValue(boundText.Target, boundText.Original); } } } private void OnDestroy() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_002e: Expected O, but got Unknown if (harmony != null) { harmony.UnpatchSelf(); } RestoreTextBindings(); if ((Object)self == (Object)this) { self = null; } } }