using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("RanongClanNameEditor")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Ranong Clan Name Editor Mod by RanongPatama")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RanongClanNameEditor")] [assembly: AssemblyTitle("RanongClanNameEditor")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RanongClanNameEditor { [BepInPlugin("com.ranongpatama.ranongclannameeditor", "Ranong Clan Name Editor", "1.0.0")] public class RanongClanNameEditorPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(SaveData), "ReadGameData")] public static class ReadGameDataPatch { [HarmonyPostfix] public static void Postfix() { Log.LogInfo((object)"Post-ReadGameData: Registering save-specific clans and applying translations."); Instance.RegisterSaveSpecificClans(); ParseMappings(); TranslateAllData(toModded: true); } } [HarmonyPatch(typeof(SaveData), "SaveGameData")] public static class SaveGameDataPatch { [HarmonyPrefix] public static void Prefix() { Log.LogInfo((object)"Pre-SaveGameData: Restoring vanilla clan names in memory for clean save."); TranslateAllData(toModded: false); } [HarmonyPostfix] public static void Postfix() { Log.LogInfo((object)"Post-SaveGameData: Re-applying modded clan names to memory."); TranslateAllData(toModded: true); } } [HarmonyPatch(typeof(RandName), "GetMemberNameShijia")] public static class GetMemberNameShijiaPatch { [HarmonyPostfix] public static void Postfix(ref string __result) { if (!string.IsNullOrEmpty(__result)) { __result = TranslateSingleName(__result, toModded: true); } } } [HarmonyPatch(typeof(JiaShiSave), "Save_JiaShi")] public static class Save_JiaShiPatch { [HarmonyPrefix] public static void Prefix(ref List MemberData) { if (MemberData != null) { for (int i = 0; i < MemberData.Count; i++) { MemberData[i] = TranslateName(MemberData[i], toModded: false); } } } [HarmonyPostfix] public static void Postfix(ref List MemberData) { if (MemberData != null) { for (int i = 0; i < MemberData.Count; i++) { MemberData[i] = TranslateName(MemberData[i], toModded: true); } } } } [HarmonyPatch(typeof(JiaShiSave), "Read_JiaShi")] public static class Read_JiaShiPatch { [HarmonyPostfix] public static void Postfix(ref List> __result) { if (__result == null) { return; } for (int i = 0; i < __result.Count; i++) { List list = __result[i]; if (list != null) { for (int j = 0; j < list.Count; j++) { list[j] = TranslateName(list[j], toModded: true); } } } } } [HarmonyPatch(typeof(JiaShiSave), "Save_GuoShi")] public static class Save_GuoShiPatch { [HarmonyPrefix] public static void Prefix(ref string ShijiaName, ref string MemberName) { ShijiaName = TranslateName(ShijiaName, toModded: false); MemberName = TranslateName(MemberName, toModded: false); } } [HarmonyPatch(typeof(JiaShiSave), "Read_GuoShi")] public static class Read_GuoShiPatch { [HarmonyPostfix] public static void Postfix(ref List __result) { if (__result != null) { for (int i = 0; i < __result.Count; i++) { __result[i] = TranslateName(__result[i], toModded: true); } } } } public const string PluginGuid = "com.ranongpatama.ranongclannameeditor"; public const string PluginName = "Ranong Clan Name Editor"; public const string PluginVersion = "1.0.0"; public const string PluginAuthor = "RanongPatama"; public static RanongClanNameEditorPlugin Instance; internal static ManualLogSource Log; private static ConfigEntry customMappingsConfig; private static Dictionary> defaultCnConfigs = new Dictionary>(); private static Dictionary> defaultEnConfigs = new Dictionary>(); private static Dictionary> playerClanConfigs = new Dictionary>(); private static Dictionary> royalClanConfigs = new Dictionary>(); private static Dictionary> npcClanConfigs = new Dictionary>(); private static Dictionary vanillaToModded = new Dictionary(); private static Dictionary moddedToVanilla = new Dictionary(); private void Awake() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; customMappingsConfig = ((BaseUnityPlugin)this).Config.Bind("Custom", "CustomClanMappings", "", "Semicolon-separated mappings for custom/player clan names. Format: Original=New (e.g. MyClan=NewName;Patama=Ranong)"); RegisterDefaultClans(); ParseMappings(); new Harmony("com.ranongpatama.ranongclannameeditor").PatchAll(); Log.LogInfo((object)"Ranong Clan Name Editor by RanongPatama initialized successfully!"); } private void RegisterDefaultClans() { try { RuntimeHelpers.RunClassConstructor(typeof(RandName).TypeHandle); if (RandName.XingShi != null) { Log.LogInfo((object)$"Found {RandName.XingShi.Count} default surnames in RandName.XingShi. Registering configs..."); { foreach (string item in RandName.XingShi) { if (string.IsNullOrEmpty(item) || !item.Contains("|")) { continue; } string[] array = item.Split(new char[1] { '|' }); if (array.Length >= 2) { string text = array[0].Trim(); string text2 = array[1].Trim(); if (!string.IsNullOrEmpty(text) && !defaultCnConfigs.ContainsKey(text)) { ConfigEntry value = ((BaseUnityPlugin)this).Config.Bind("Default Clans (Chinese)", text, text, "Map Chinese clan surname '" + text + "' to a new surname."); defaultCnConfigs[text] = value; } if (!string.IsNullOrEmpty(text2) && !defaultEnConfigs.ContainsKey(text2)) { ConfigEntry value2 = ((BaseUnityPlugin)this).Config.Bind("Default Clans (English)", text2, text2, "Map English clan surname '" + text2 + "' to a new surname."); defaultEnConfigs[text2] = value2; } } } return; } } Log.LogWarning((object)"RandName.XingShi list is null. Surnames could not be pre-populated."); } catch (Exception arg) { Log.LogError((object)$"Error registering default game clans: {arg}"); } } public void RegisterSaveSpecificClans() { try { if (Mainload.FamilyData != null && Mainload.FamilyData.Count > 1) { string text = Mainload.FamilyData[1]?.Trim(); if (!string.IsNullOrEmpty(text) && !playerClanConfigs.ContainsKey(text)) { Log.LogInfo((object)("Dynamically registering Player Clan surname: " + text)); ConfigEntry value = ((BaseUnityPlugin)this).Config.Bind("Player Clan (Save-specific)", text, text, "Map Player clan surname '" + text + "' to a new surname."); playerClanConfigs[text] = value; } } if (Mainload.ShiJia_king != null && Mainload.ShiJia_king.Count > 0) { string text2 = Mainload.ShiJia_king[0]?.Trim(); if (!string.IsNullOrEmpty(text2) && !royalClanConfigs.ContainsKey(text2)) { Log.LogInfo((object)("Dynamically registering Royal Clan surname: " + text2)); ConfigEntry value2 = ((BaseUnityPlugin)this).Config.Bind("Royal Clan (Save-specific)", text2, text2, "Map Royal clan surname '" + text2 + "' to a new surname."); royalClanConfigs[text2] = value2; } } if (Mainload.ShiJia_Now == null) { return; } for (int i = 0; i < Mainload.ShiJia_Now.Count; i++) { List list = Mainload.ShiJia_Now[i]; if (list != null && list.Count > 1) { string text3 = list[1]?.Trim(); if (!string.IsNullOrEmpty(text3) && !npcClanConfigs.ContainsKey(text3)) { Log.LogInfo((object)("Dynamically registering NPC Noble Clan surname: " + text3)); ConfigEntry value3 = ((BaseUnityPlugin)this).Config.Bind("NPC Noble Clans (Save-specific)", text3, text3, "Map NPC Noble clan surname '" + text3 + "' to a new surname."); npcClanConfigs[text3] = value3; } } } } catch (Exception arg) { Log.LogError((object)$"Error registering save-specific clans: {arg}"); } } private static void ParseMappings() { try { vanillaToModded.Clear(); moddedToVanilla.Clear(); string value = customMappingsConfig.Value; if (!string.IsNullOrEmpty(value)) { string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '=' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2) { AddMapping(array2[0], array2[1]); } } } foreach (KeyValuePair> defaultCnConfig in defaultCnConfigs) { AddMapping(defaultCnConfig.Key, defaultCnConfig.Value.Value); } foreach (KeyValuePair> defaultEnConfig in defaultEnConfigs) { AddMapping(defaultEnConfig.Key, defaultEnConfig.Value.Value); } foreach (KeyValuePair> playerClanConfig in playerClanConfigs) { AddMapping(playerClanConfig.Key, playerClanConfig.Value.Value); } foreach (KeyValuePair> royalClanConfig in royalClanConfigs) { AddMapping(royalClanConfig.Key, royalClanConfig.Value.Value); } foreach (KeyValuePair> npcClanConfig in npcClanConfigs) { AddMapping(npcClanConfig.Key, npcClanConfig.Value.Value); } Log.LogInfo((object)$"Parsed {vanillaToModded.Count} clan name mapping(s)."); } catch (Exception arg) { Log.LogError((object)$"Error parsing clan mappings: {arg}"); } static void AddMapping(string vanilla, string modded) { if (!string.IsNullOrEmpty(vanilla) && !string.IsNullOrEmpty(modded)) { vanilla = vanilla.Trim(); modded = modded.Trim(); if (vanilla != modded) { vanillaToModded[vanilla] = modded; moddedToVanilla[modded] = vanilla; } } } } public static string TranslateName(string name, bool toModded) { if (string.IsNullOrEmpty(name)) { return name; } try { if (name.Contains("|")) { string[] array = name.Split(new char[1] { '|' }); if (array.Length != 0) { array[0] = TranslateSingleName(array[0], toModded); if (array.Length > 2) { array[2] = TranslateSingleName(array[2], toModded); } else if (array.Length > 1) { array[1] = TranslateSingleName(array[1], toModded); } return string.Join("|", array); } } return TranslateSingleName(name, toModded); } catch (Exception arg) { Log.LogError((object)$"Error in TranslateName: {arg}"); return name; } } public static string TranslateSingleName(string name, bool toModded) { if (string.IsNullOrEmpty(name)) { return name; } Dictionary dictionary = (toModded ? vanillaToModded : moddedToVanilla); if (dictionary.Count == 0) { return name; } foreach (KeyValuePair item in dictionary) { string key = item.Key; string value = item.Value; if (name == key) { return value; } if (name.StartsWith(key)) { return value + name.Substring(key.Length); } if (name.EndsWith(" " + key)) { return name.Substring(0, name.Length - key.Length) + value; } } return name; } public static void TranslateMember(List member, bool toModded, bool isMemberNow) { if (member == null || member.Count == 0) { return; } try { int num = (isMemberNow ? 4 : 2); if (num < member.Count) { member[num] = TranslateName(member[num], toModded); } if (isMemberNow && 2 < member.Count) { string text = member[2]; if (text != null && text.Contains("|")) { member[2] = TranslateName(text, toModded); } } } catch (Exception arg) { Log.LogError((object)$"Error in TranslateMember: {arg}"); } } public static void TranslateAllData(bool toModded) { try { Log.LogInfo((object)$"Translating game data (toModded: {toModded})..."); if (Mainload.FamilyData != null) { for (int i = 0; i < Mainload.FamilyData.Count; i++) { Mainload.FamilyData[i] = TranslateName(Mainload.FamilyData[i], toModded); } } if (Mainload.ShiJia_king != null) { for (int j = 0; j < Mainload.ShiJia_king.Count; j++) { Mainload.ShiJia_king[j] = TranslateName(Mainload.ShiJia_king[j], toModded); } } if (Mainload.ShiJia_Now != null) { for (int k = 0; k < Mainload.ShiJia_Now.Count; k++) { List list = Mainload.ShiJia_Now[k]; if (list != null) { for (int l = 0; l < list.Count; l++) { list[l] = TranslateName(list[l], toModded); } } } } TranslateList2D(Mainload.Member_now, isMemberNow: true); TranslateList2D(Mainload.Member_qu, isMemberNow: false); TranslateList2D(Mainload.Member_King, isMemberNow: false); TranslateList2D(Mainload.Member_King_qu, isMemberNow: false); TranslateList2D(Mainload.Member_Hanmen, isMemberNow: false); TranslateList2D(Mainload.Member_Ci, isMemberNow: false); TranslateList2D(Mainload.MenKe_Now, isMemberNow: false); TranslateList3D(Mainload.Member_other); TranslateList3D(Mainload.Member_Other_qu); TranslateList3D(Mainload.Member_Qinglou); TranslateList3D(Mainload.Doctor_now); TranslateList4D(Mainload.ZhuangTou_now); Log.LogInfo((object)"Game data translation complete."); } catch (Exception arg) { Log.LogError((object)$"Error in TranslateAllData: {arg}"); } void TranslateList2D(List> list2, bool isMemberNow) { if (list2 != null) { for (int m = 0; m < list2.Count; m++) { TranslateMember(list2[m], toModded, isMemberNow); } } } void TranslateList3D(List>> list2) { if (list2 != null) { for (int m = 0; m < list2.Count; m++) { List> list3 = list2[m]; if (list3 != null) { for (int n = 0; n < list3.Count; n++) { TranslateMember(list3[n], toModded, isMemberNow: false); } } } } } void TranslateList4D(List>>> list2) { if (list2 != null) { for (int m = 0; m < list2.Count; m++) { List>> list3 = list2[m]; if (list3 != null) { for (int n = 0; n < list3.Count; n++) { List> list4 = list3[n]; if (list4 != null) { for (int num = 0; num < list4.Count; num++) { TranslateMember(list4[num], toModded, isMemberNow: false); } } } } } } } } } }