Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of RenameNPCs v1.0.0
RenameNPCs.dll
Decompiled 18 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using RenameNPCs; using RenameNPCs.Features; using RenameNPCs.Patches; using RenameNPCs.Utils; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "RenameNPCs", "1.0.0", "HazDS", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RenameNPCs")] [assembly: AssemblyConfiguration("CrossCompat")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+27f3ca42ec72c7ad7af5d6e91469ba0f1a9b3eb2")] [assembly: AssemblyProduct("RenameNPCs")] [assembly: AssemblyTitle("RenameNPCs")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 RenameNPCs { public class Core : MelonMod { [CompilerGenerated] private sealed class <ApplyNamesDelayed>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Core <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyNamesDelayed>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; NpcFieldModifier.ApplyAllCustomNames(); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 2; return true; case 2: <>1__state = -1; MapPoiRefresher.RefreshAllPoIs(); MessagingNameRefresher.RefreshAllConversations(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private bool _initialized = false; public static Core Instance { get; private set; } public override void OnInitializeMelon() { Instance = this; Config.Initialize(); NpcNameManager.Initialize(); NpcNamePatches.ApplyPatches(); ((MelonBase)this).LoggerInstance.Msg("RenameNPCs v1.0.0 initialized!"); ((MelonBase)this).LoggerInstance.Msg("Press N while looking at an NPC to rename them."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName == "Menu") { _initialized = false; NpcFieldModifier.Reset(); RenamePromptUI.Destroy(); DebugLog.Msg("Menu scene loaded - resetting state"); } } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (sceneName == "Main") { if (!_initialized) { NpcNameManager.Initialize(); _initialized = true; } else { NpcNameManager.Reload(); } MelonCoroutines.Start(ApplyNamesDelayed()); DebugLog.Msg("Main scene initialized - mod ready"); } } [IteratorStateMachine(typeof(<ApplyNamesDelayed>d__8))] private IEnumerator ApplyNamesDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ApplyNamesDelayed>d__8(0) { <>4__this = this }; } public override void OnUpdate() { if (_initialized) { NpcRenameController.Update(); } } public override void OnDeinitializeMelon() { DebugLog.Msg("Mod deinitialized"); } } public static class Config { private static MelonPreferences_Category _category; private static MelonPreferences_Entry<bool> _enabled; private static MelonPreferences_Entry<int> _maxNameLength; private static MelonPreferences_Entry<bool> _debugLogs; private static MelonPreferences_Entry<bool> _showRenamePrompt; public static bool Enabled => _enabled?.Value ?? true; public static int MaxNameLength => _maxNameLength?.Value ?? 30; public static bool DebugLogsEnabled => _debugLogs?.Value ?? false; public static bool ShowRenamePrompt => _showRenamePrompt?.Value ?? true; public static void Initialize() { _category = MelonPreferences.CreateCategory("RenameNPCs", "Rename NPCs Settings"); _enabled = _category.CreateEntry<bool>("Enabled", true, "Enable Mod", "Master toggle for the rename NPCs feature", false, false, (ValueValidator)null, (string)null); _maxNameLength = _category.CreateEntry<int>("MaxNameLength", 30, "Max Name Length", "Maximum characters allowed for custom names", false, false, (ValueValidator)null, (string)null); _debugLogs = _category.CreateEntry<bool>("DebugLogs", false, "Debug Logs", "Enable debug logging for troubleshooting", false, false, (ValueValidator)null, (string)null); _showRenamePrompt = _category.CreateEntry<bool>("ShowRenamePrompt", true, "Show Rename Prompt", "Show [N] Rename prompt when looking at an NPC", false, false, (ValueValidator)null, (string)null); } } } namespace RenameNPCs.Patches { public static class NpcNamePatches { private static Harmony _harmony; public static void ApplyPatches() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown try { _harmony = new Harmony("com.renamenpc.patches"); PatchFullName(); if (!GameTypes.IsIl2Cpp) { PatchGetNameAddress(); } PatchCustomerSelectorOpen(); DebugLog.Msg("All NPC name patches applied successfully"); } catch (Exception ex) { DebugLog.Error("Failed to apply patches: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } public static void RemovePatches() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private static void PatchFullName() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown try { Type nPC = GameTypes.NPC; if (nPC == null) { DebugLog.Error("Could not resolve NPC type for fullName patch"); return; } PropertyInfo property = nPC.GetProperty("fullName", BindingFlags.Instance | BindingFlags.Public); if (property == null) { DebugLog.Error("Could not find NPC.fullName property"); return; } MethodInfo getMethod = property.GetGetMethod(); if (getMethod == null) { DebugLog.Error("Could not find NPC.fullName getter"); return; } MethodInfo method = typeof(NpcNamePatches).GetMethod("FullName_Prefix", BindingFlags.Static | BindingFlags.Public); _harmony.Patch((MethodBase)getMethod, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); DebugLog.Msg("Patched NPC.fullName getter"); } catch (Exception ex) { DebugLog.Error("Failed to patch fullName: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static void PatchGetNameAddress() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown try { Type nPC = GameTypes.NPC; if (nPC == null) { DebugLog.Error("Could not resolve NPC type for GetNameAddress patch"); return; } MethodInfo method = nPC.GetMethod("GetNameAddress", BindingFlags.Instance | BindingFlags.Public); if (method == null) { DebugLog.Error("Could not find NPC.GetNameAddress method"); return; } MethodInfo method2 = typeof(NpcNamePatches).GetMethod("GetNameAddress_Prefix", BindingFlags.Static | BindingFlags.Public); _harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); DebugLog.Msg("Patched NPC.GetNameAddress method"); } catch (Exception ex) { DebugLog.Error("Failed to patch GetNameAddress: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static void PatchCustomerSelectorOpen() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown try { Type customerSelector = GameTypes.CustomerSelector; if (customerSelector == null) { DebugLog.Error("Could not resolve CustomerSelector type"); return; } MethodInfo method = customerSelector.GetMethod("Open", BindingFlags.Instance | BindingFlags.Public); if (method == null) { DebugLog.Error("Could not find CustomerSelector.Open method"); return; } MethodInfo method2 = typeof(NpcNamePatches).GetMethod("CustomerSelectorOpen_Postfix", BindingFlags.Static | BindingFlags.Public); _harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); DebugLog.Msg("Patched CustomerSelector.Open"); } catch (Exception ex) { DebugLog.Error("Failed to patch CustomerSelector.Open: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } public static void CustomerSelectorOpen_Postfix(object __instance) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) if (!Config.Enabled) { return; } try { Type type = __instance.GetType(); object memberValue = GetMemberValue(__instance, type, "customerEntries"); object memberValue2 = GetMemberValue(__instance, type, "entryToCustomer"); if (memberValue == null || memberValue2 == null) { return; } Color val = Color.gray; try { Type phone = GameTypes.Phone; if (phone != null && GameSingletons.PlayerSingletonExists(phone)) { object playerSingleton = GameSingletons.GetPlayerSingleton(phone); if (playerSingleton != null) { object value = ReflectionHelper.GetValue(playerSingleton, "GeneralColorFont"); if (value != null) { MethodInfo method = value.GetType().GetMethod("GetColour", new Type[1] { typeof(string) }); if (method != null) { object obj = method.Invoke(value, new object[1] { "FadedText" }); if (obj is Color) { Color val2 = (Color)obj; if (true) { val = val2; } } } } } } } catch { } Type type2 = memberValue.GetType(); PropertyInfo property = type2.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return; } int num = (int)property.GetValue(memberValue); PropertyInfo propertyInfo = type2.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public) ?? type2.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public)?.DeclaringType.GetProperty("Item"); MethodInfo method2 = type2.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public); Type type3 = memberValue2.GetType(); MethodInfo method3 = type3.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public); if (method2 == null || method3 == null) { return; } for (int i = 0; i < num; i++) { object obj3 = method2.Invoke(memberValue, new object[1] { i }); RectTransform val3 = null; RectTransform val4 = (RectTransform)((obj3 is RectTransform) ? obj3 : null); if (val4 != null) { val3 = val4; } else { Transform val5 = (Transform)((obj3 is Transform) ? obj3 : null); if (val5 != null) { val3 = ((Component)val5).GetComponent<RectTransform>(); } else { Component val6 = (Component)((obj3 is Component) ? obj3 : null); if (val6 != null) { val3 = val6.GetComponent<RectTransform>(); } } } if ((Object)(object)val3 == (Object)null || !((Component)val3).gameObject.activeSelf) { continue; } object obj4 = null; try { obj4 = method3.Invoke(memberValue2, new object[1] { obj3 }); } catch { continue; } if (obj4 == null) { continue; } object value2 = ReflectionHelper.GetValue(obj4, "NPC"); if (value2 == null) { continue; } string iD = NpcAccess.GetID(value2); if (string.IsNullOrEmpty(iD) || !NpcNameManager.HasCustomName(iD)) { continue; } Transform val7 = ((Transform)val3).Find("Name"); if (!((Object)(object)val7 == (Object)null)) { Text component = ((Component)val7).GetComponent<Text>(); if (!((Object)(object)component == (Object)null)) { string text = NpcNameManager.GetCustomFullNameById(iD) ?? NpcAccess.GetFullName(value2); string region = NpcAccess.GetRegion(value2); component.text = text + "<color=#" + ColorUtility.ToHtmlStringRGBA(val) + "> (" + region + ")</color>"; } } } } catch (Exception ex) { DebugLog.Error("Error in CustomerSelectorOpen_Postfix: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static object GetMemberValue(object instance, Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(instance); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(instance); } return null; } public static bool FullName_Prefix(object __instance, ref string __result) { if (!Config.Enabled) { return true; } try { if (__instance == null) { return true; } if (GameTypes.IsIl2Cpp) { try { PropertyInfo property = __instance.GetType().GetProperty("WasCollected", BindingFlags.Instance | BindingFlags.Public); if (property != null) { object value = property.GetValue(__instance); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } } catch { return true; } } string iD = NpcAccess.GetID(__instance); if (string.IsNullOrEmpty(iD)) { return true; } string customFullNameById = NpcNameManager.GetCustomFullNameById(iD); if (customFullNameById != null) { __result = customFullNameById; return false; } } catch (Exception ex) { DebugLog.Error("Error in FullName_Prefix: " + ex.Message); } return true; } public static bool GetNameAddress_Prefix(object __instance, ref string __result) { if (!Config.Enabled) { return true; } try { if (__instance == null) { return true; } string iD = NpcAccess.GetID(__instance); if (string.IsNullOrEmpty(iD)) { return true; } if (NpcNameManager.HasCustomName(iD)) { __result = NpcNameManager.GetCustomName(iD).FirstName; return false; } } catch (Exception ex) { DebugLog.Error("Error in GetNameAddress_Prefix: " + ex.Message); } return true; } } } namespace RenameNPCs.Features { public static class NpcNameManager { public struct CustomName { public string FirstName; public string LastName; public bool HasLastName; } private static MelonPreferences_Category _namesCategory; private static Dictionary<string, CustomName> _customNames = new Dictionary<string, CustomName>(); private static bool _initialized = false; private static string _configFilePath; public static void Initialize() { if (_namesCategory == null) { _namesCategory = MelonPreferences.CreateCategory("RenameNPCs_Names", "NPC Custom Names"); } _configFilePath = Path.Combine(MelonEnvironment.UserDataDirectory, "MelonPreferences.cfg"); if (!_initialized) { LoadAllNames(); _initialized = true; DebugLog.Msg($"NpcNameManager initialized with {_customNames.Count} custom names"); } } public static void Reload() { LoadAllNames(); DebugLog.Msg($"NpcNameManager reloaded with {_customNames.Count} custom names"); } public static void RefreshMapPoIs() { MapPoiRefresher.RefreshAllPoIs(); } public static void Reset() { _customNames.Clear(); _initialized = false; NpcFieldModifier.Reset(); } private static void LoadAllNames() { _customNames.Clear(); try { if (string.IsNullOrEmpty(_configFilePath) || !File.Exists(_configFilePath)) { DebugLog.Msg("Config file not found, no names to load"); return; } string[] array = File.ReadAllLines(_configFilePath); bool flag = false; string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.StartsWith("[")) { flag = text2 == "[RenameNPCs_Names]"; } else { if (!flag || string.IsNullOrEmpty(text2) || text2.StartsWith("#")) { continue; } int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string text4 = text2.Substring(num + 1).Trim(); if (text4.StartsWith("\"") && text4.EndsWith("\"")) { text4 = text4.Substring(1, text4.Length - 2); } if (!string.IsNullOrEmpty(text4)) { CustomName value = ParseStoredName(text4); _customNames[text3] = value; DebugLog.Msg("Loaded custom name for " + text3 + ": " + value.FirstName + " " + value.LastName); } } } } } catch (Exception ex) { DebugLog.Error("Error loading names from config: " + ex.Message); } } private static CustomName ParseStoredName(string storedValue) { string[] array = storedValue.Split(new string[1] { "|" }, StringSplitOptions.None); CustomName result = default(CustomName); result.FirstName = ((array.Length != 0) ? array[0] : ""); result.LastName = ((array.Length > 1) ? array[1] : ""); result.HasLastName = array.Length > 1 && !string.IsNullOrEmpty(array[1]); return result; } private static string FormatForStorage(CustomName name) { if (name.HasLastName && !string.IsNullOrEmpty(name.LastName)) { return name.FirstName + "|" + name.LastName; } return name.FirstName + "|"; } public static bool HasCustomName(string npcId) { return !string.IsNullOrEmpty(npcId) && _customNames.ContainsKey(npcId); } public static CustomName GetCustomName(string npcId) { if (_customNames.TryGetValue(npcId, out var value)) { return value; } return default(CustomName); } public static string GetCustomFullName(object npc) { if (npc == null) { return null; } string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { return null; } return GetCustomFullNameById(iD); } public static string GetCustomFullNameById(string npcId) { if (string.IsNullOrEmpty(npcId)) { return null; } if (_customNames.TryGetValue(npcId, out var value)) { return value.HasLastName ? (value.FirstName + " " + value.LastName) : value.FirstName; } return null; } public static string GetCustomFirstName(object npc) { if (npc == null) { return null; } string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { return null; } if (_customNames.TryGetValue(iD, out var value)) { return value.FirstName; } return null; } public static void SetCustomName(object npc, string firstName, string lastName = null) { if (npc == null) { return; } string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { DebugLog.Warning("Cannot set custom name: NPC or NPC.ID is null"); return; } CustomName customName = default(CustomName); customName.FirstName = firstName.Trim(); customName.LastName = lastName?.Trim() ?? ""; customName.HasLastName = !string.IsNullOrEmpty(lastName?.Trim()); CustomName customName2 = customName; _customNames[iD] = customName2; MelonPreferences_Entry<string> entry = _namesCategory.GetEntry<string>(iD); if (entry == null) { entry = _namesCategory.CreateEntry<string>(iD, FormatForStorage(customName2), iD, "Custom name for " + NpcAccess.GetFirstName(npc) + " " + NpcAccess.GetLastName(npc), false, false, (ValueValidator)null, (string)null); } else { entry.Value = FormatForStorage(customName2); } MelonPreferences.Save(); DebugLog.Msg("Set custom name for " + iD + ": " + firstName + " " + lastName); NpcFieldModifier.ApplyCustomName(npc); MapPoiRefresher.RefreshNpcPoIs(npc); MessagingNameRefresher.RefreshNpcConversation(npc); } public static void ResetName(object npc) { if (npc == null) { return; } string iD = NpcAccess.GetID(npc); if (!string.IsNullOrEmpty(iD) && _customNames.ContainsKey(iD)) { NpcFieldModifier.RestoreOriginalName(npc); _customNames.Remove(iD); MelonPreferences_Entry<string> entry = _namesCategory.GetEntry<string>(iD); if (entry != null) { _namesCategory.DeleteEntry(iD); } MelonPreferences.Save(); MapPoiRefresher.RefreshNpcPoIs(npc); MessagingNameRefresher.RefreshNpcConversation(npc); DebugLog.Msg("Reset name for " + iD); } } public static Dictionary<string, CustomName> GetAllCustomNames() { return new Dictionary<string, CustomName>(_customNames); } } public static class NpcRenameController { private const KeyCode RENAME_KEY = 110; private static bool _isRenaming; private static object _pendingNpc; private static MethodInfo _lookRaycastMethod; private static PropertyInfo _isOpenProperty; private static MethodInfo _openMethod; private static PropertyInfo _hoveredInteractableProp; private static bool _reflectionResolved; public static void Reset() { _isRenaming = false; _pendingNpc = null; RenamePromptUI.Hide(); } private static void EnsureReflection() { if (_reflectionResolved) { return; } _reflectionResolved = true; Type playerCamera = GameTypes.PlayerCamera; if (playerCamera != null) { _lookRaycastMethod = playerCamera.GetMethod("LookRaycast", BindingFlags.Instance | BindingFlags.Public); } Type textInputScreen = GameTypes.TextInputScreen; if (textInputScreen != null) { _isOpenProperty = textInputScreen.GetProperty("IsOpen", BindingFlags.Instance | BindingFlags.Public); _openMethod = textInputScreen.GetMethod("Open", new Type[4] { typeof(string), typeof(string), textInputScreen.GetNestedType("OnSubmit") ?? typeof(Delegate), typeof(int) }); if (_openMethod == null) { MethodInfo[] methods = textInputScreen.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "Open" && methodInfo.GetParameters().Length == 4) { _openMethod = methodInfo; break; } } } } Type interactionManager = GameTypes.InteractionManager; if (interactionManager != null) { _hoveredInteractableProp = interactionManager.GetProperty("HoveredInteractableObject", BindingFlags.Instance | BindingFlags.Public); } } public static void Update() { if (!Config.Enabled) { return; } if (_isRenaming) { RenamePromptUI.Hide(); Type textInputScreen = GameTypes.TextInputScreen; if (textInputScreen != null && GameSingletons.SingletonExists(textInputScreen)) { object singleton = GameSingletons.GetSingleton(textInputScreen); EnsureReflection(); if (singleton == null || !IsTextInputOpen(singleton)) { DebugLog.Msg("TextInputScreen closed, resetting _isRenaming"); _isRenaming = false; _pendingNpc = null; } } else { _isRenaming = false; _pendingNpc = null; } return; } UpdatePrompt(); if (!Input.GetKeyDown((KeyCode)110)) { return; } DebugLog.Msg("N key pressed"); if (!CanInteract()) { DebugLog.Msg("CanInteract returned false"); return; } object lookedAtNpc = GetLookedAtNpc(); if (lookedAtNpc != null) { DebugLog.Msg("Found NPC: " + NpcAccess.GetID(lookedAtNpc)); OpenRenameDialog(lookedAtNpc); } else { DebugLog.Msg("No NPC found in raycast"); } } private static void UpdatePrompt() { if (!Config.ShowRenamePrompt) { RenamePromptUI.Hide(); return; } object hoveredNpc = GetHoveredNpc(); if (hoveredNpc != null) { RenamePromptUI.Show(); } else { RenamePromptUI.Hide(); } } private static object GetHoveredNpc() { try { EnsureReflection(); Type interactionManager = GameTypes.InteractionManager; if (interactionManager == null || !GameSingletons.SingletonExists(interactionManager)) { return null; } object singleton = GameSingletons.GetSingleton(interactionManager); if (singleton == null || _hoveredInteractableProp == null) { return null; } object? value = _hoveredInteractableProp.GetValue(singleton); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val == (Object)null) { return null; } Type nPC = GameTypes.NPC; if (nPC == null) { return null; } return GameTypes.GetComponentInParent(val, nPC); } catch { return null; } } private static bool IsTextInputOpen(object textInput) { if (textInput == null) { return false; } EnsureReflection(); try { object obj = _isOpenProperty?.GetValue(textInput); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static bool CanInteract() { try { Type playerCamera = GameTypes.PlayerCamera; if (playerCamera == null || !GameSingletons.PlayerSingletonExists(playerCamera)) { return false; } Type textInputScreen = GameTypes.TextInputScreen; if (textInputScreen != null && GameSingletons.SingletonExists(textInputScreen)) { object singleton = GameSingletons.GetSingleton(textInputScreen); if (singleton != null && IsTextInputOpen(singleton)) { return false; } } return true; } catch { return false; } } private static object GetLookedAtNpc() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) try { Type playerCamera = GameTypes.PlayerCamera; if (playerCamera == null || !GameSingletons.PlayerSingletonExists(playerCamera)) { return null; } object playerSingleton = GameSingletons.GetPlayerSingleton(playerCamera); if (playerSingleton == null) { return null; } EnsureReflection(); if (_lookRaycastMethod == null) { return null; } LayerMask val = LayerMask.op_Implicit(LayerMask.GetMask(new string[2] { "Default", "NPC" })); object[] array = new object[5] { 5f, null, val, true, 0.1f }; object obj = _lookRaycastMethod.Invoke(playerSingleton, array); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { RaycastHit val2 = (RaycastHit)array[1]; Collider collider = ((RaycastHit)(ref val2)).collider; if ((Object)(object)collider != (Object)null) { Type nPC = GameTypes.NPC; if (nPC != null) { return GameTypes.GetComponentInParent((Component)(object)collider, nPC); } } } return null; } catch (Exception ex) { DebugLog.Error("Error in GetLookedAtNpc: " + ex.Message); return null; } } private static void OpenRenameDialog(object npc) { string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { DebugLog.Warning("Cannot rename: NPC or NPC.ID is null"); return; } try { Type textInputScreen = GameTypes.TextInputScreen; if (textInputScreen == null || !GameSingletons.SingletonExists(textInputScreen)) { DebugLog.Warning("TextInputScreen not available"); return; } object singleton = GameSingletons.GetSingleton(textInputScreen); if (singleton == null) { DebugLog.Warning("TextInputScreen instance is null"); return; } _isRenaming = true; _pendingNpc = npc; string text = (NpcNameManager.HasCustomName(iD) ? NpcNameManager.GetCustomFullName(npc) : NpcAccess.GetFullName(npc)); string text2 = "Rename " + NpcAccess.GetFullName(npc); DebugLog.Msg("Opening rename dialog for " + iD + " with current name: " + text); EnsureReflection(); Type nestedType = textInputScreen.GetNestedType("OnSubmit"); if (nestedType == null) { DebugLog.Error("Could not find TextInputScreen.OnSubmit type"); _isRenaming = false; _pendingNpc = null; return; } Action<string> action = OnNameSubmittedCallback; object obj; if (GameTypes.IsIl2Cpp) { Type type = Type.GetType("Il2CppInterop.Runtime.DelegateSupport, Il2CppInterop.Runtime"); if (!(type != null)) { DebugLog.Error("Could not find DelegateSupport for IL2CPP"); _isRenaming = false; _pendingNpc = null; return; } obj = (type.GetMethod("ConvertDelegate")?.MakeGenericMethod(nestedType))?.Invoke(null, new object[1] { action }); } else { obj = Delegate.CreateDelegate(nestedType, action.Target, action.Method); } if (_openMethod != null && obj != null) { _openMethod.Invoke(singleton, new object[4] { text2, text, obj, Config.MaxNameLength }); } else { DebugLog.Error("Could not invoke TextInputScreen.Open"); _isRenaming = false; _pendingNpc = null; } } catch (Exception ex) { DebugLog.Error("Error opening rename dialog: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); _isRenaming = false; _pendingNpc = null; } } private static void OnNameSubmittedCallback(string newName) { _isRenaming = false; object pendingNpc = _pendingNpc; _pendingNpc = null; if (pendingNpc == null) { DebugLog.Warning("OnNameSubmittedCallback: _pendingNpc was null"); return; } try { if (string.IsNullOrWhiteSpace(newName)) { NpcNameManager.ResetName(pendingNpc); DebugLog.Msg("Reset name for " + NpcAccess.GetID(pendingNpc)); return; } newName = newName.Trim(); if (newName.Length > Config.MaxNameLength) { newName = newName.Substring(0, Config.MaxNameLength); } string[] array = newName.Split(new char[1] { ' ' }, 2); string text = array[0]; string text2 = ((array.Length > 1) ? array[1] : ""); NpcNameManager.SetCustomName(pendingNpc, text, text2); DebugLog.Msg("Set name for " + NpcAccess.GetID(pendingNpc) + ": " + text + " " + text2); } catch (Exception ex) { DebugLog.Error("Error in OnNameSubmittedCallback: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } } public static class RenamePromptUI { private static GameObject _promptObj; private static bool _isShowing; private const float Y_OFFSET = -55f; public static void Show() { if (EnsureUI()) { _promptObj.SetActive(true); _isShowing = true; } } public static void Hide() { if (_isShowing) { if ((Object)(object)_promptObj != (Object)null) { _promptObj.SetActive(false); } _isShowing = false; } } public static void Destroy() { if ((Object)(object)_promptObj != (Object)null) { Object.Destroy((Object)(object)_promptObj); _promptObj = null; } _isShowing = false; } private static bool EnsureUI() { //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_promptObj != (Object)null) { return true; } try { Type type = GameTypes.Resolve("UI.InteractionCanvas"); if (type == null) { DebugLog.Error("RenamePromptUI: InteractionCanvas type not found"); return false; } if (!GameSingletons.SingletonExists(type)) { return false; } object singleton = GameSingletons.GetSingleton(type); if (singleton == null) { return false; } object value = ReflectionHelper.GetValue(singleton, "Container"); if (value == null) { DebugLog.Error("RenamePromptUI: Container is null"); return false; } RectTransform val = (RectTransform)((value is RectTransform) ? value : null); if ((Object)(object)val == (Object)null) { Component val2 = (Component)((value is Component) ? value : null); if (val2 != null) { Transform transform = val2.transform; val = (RectTransform)(object)((transform is RectTransform) ? transform : null); } } if ((Object)(object)val == (Object)null) { DebugLog.Error("RenamePromptUI: Container is not RectTransform, type: " + value.GetType().FullName); return false; } object value2 = ReflectionHelper.GetValue(singleton, "Icon"); object value3 = ReflectionHelper.GetValue(singleton, "IconText"); object value4 = ReflectionHelper.GetValue(singleton, "MessageText"); GameObject val3 = null; GameObject val4 = null; Component val5 = (Component)((value2 is Component) ? value2 : null); if (val5 != null) { val3 = val5.gameObject; } Component val6 = (Component)((value4 is Component) ? value4 : null); if (val6 != null) { val4 = val6.gameObject; } if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { DebugLog.Error($"RenamePromptUI: Could not get game UI objects. Icon={value2 != null}, MessageText={value4 != null}"); return false; } object obj = null; object obj2 = null; if (value3 != null) { obj = ReflectionHelper.GetValue(value3, "text"); } if (value4 != null) { obj2 = ReflectionHelper.GetValue(value4, "text"); } if (value3 != null) { ReflectionHelper.SetValue(value3, "text", "N"); } if (value4 != null) { ReflectionHelper.SetValue(value4, "text", "To rename"); } _promptObj = new GameObject("RenamePrompt"); RectTransform val7 = _promptObj.AddComponent<RectTransform>(); ((Transform)val7).SetParent((Transform)(object)val, false); val7.anchoredPosition = new Vector2(0f, -55f); val7.anchorMin = new Vector2(0.5f, 0.5f); val7.anchorMax = new Vector2(0.5f, 0.5f); val7.pivot = new Vector2(0.5f, 0.5f); val7.sizeDelta = val.sizeDelta; GameObject val8 = Object.Instantiate<GameObject>(val3, _promptObj.transform, false); ((Object)val8).name = "RenameIcon"; val8.transform.localScale = val3.transform.localScale; GameObject val9 = Object.Instantiate<GameObject>(val4, _promptObj.transform, false); ((Object)val9).name = "RenameMessageText"; for (int num = val9.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)val9.transform.GetChild(num)).gameObject); } if (value3 != null && obj != null) { ReflectionHelper.SetValue(value3, "text", obj); } if (value4 != null && obj2 != null) { ReflectionHelper.SetValue(value4, "text", obj2); } _promptObj.SetActive(false); DebugLog.Msg("RenamePromptUI: Created prompt by cloning game UI elements"); return true; } catch (Exception ex) { DebugLog.Error("RenamePromptUI: Init failed: " + ex.Message); DebugLog.Error("RenamePromptUI: Stack trace: " + ex.StackTrace); return false; } } } public static class MapPoiRefresher { public static void RefreshAllPoIs() { if (!Config.Enabled) { return; } try { Type nPCPoI = GameTypes.NPCPoI; if (nPCPoI == null) { DebugLog.Msg("NPCPoI type not resolved"); return; } Object[] array = GameTypes.FindObjectsOfType(nPCPoI); int num = 0; Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null) && RefreshPoI(val)) { num++; } } if (num > 0) { DebugLog.Msg($"Refreshed {num} map POI labels"); } } catch (Exception ex) { DebugLog.Error("Error refreshing POIs: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } public static void RefreshNpcPoIs(object npc) { if (!Config.Enabled || npc == null) { return; } try { Type nPCPoI = GameTypes.NPCPoI; if (nPCPoI == null) { return; } string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { return; } Object[] array = GameTypes.FindObjectsOfType(nPCPoI); Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null)) { object value = ReflectionHelper.GetValue(val, "NPC"); if (value != null && !(NpcAccess.GetID(value) != iD)) { RefreshPoI(val); } } } RefreshDealerPoIs(npc); } catch (Exception ex) { DebugLog.Error("Error refreshing NPC POIs: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static bool RefreshPoI(object poi) { if (poi == null) { return false; } object value = ReflectionHelper.GetValue(poi, "NPC"); if (value == null) { return false; } string iD = NpcAccess.GetID(value); if (string.IsNullOrEmpty(iD)) { return false; } if (!NpcNameManager.HasCustomName(iD)) { return false; } string text = ReflectionHelper.GetValue(poi, "MainText") as string; if (string.IsNullOrEmpty(text)) { return false; } string updatedPoiText = GetUpdatedPoiText(value, text); if (updatedPoiText != null && updatedPoiText != text) { ReflectionHelper.InvokeMethod(poi, "SetMainText", new object[1] { updatedPoiText }); DebugLog.Msg("Updated POI text for " + iD + ": " + updatedPoiText); return true; } return false; } private static void RefreshDealerPoIs(object npc) { if (!NpcAccess.IsDealer(npc)) { return; } try { string iD = NpcAccess.GetID(npc); string customFullName = NpcNameManager.GetCustomFullName(npc); if (!string.IsNullOrEmpty(customFullName)) { object value = ReflectionHelper.GetValue(npc, "DealerPoI"); if (value != null) { ReflectionHelper.InvokeMethod(value, "SetMainText", new object[1] { customFullName + "\n(Dealer)" }); DebugLog.Msg("Updated DealerPoI for " + iD); } object value2 = ReflectionHelper.GetValue(npc, "PotentialDealerPoI"); if (value2 != null) { ReflectionHelper.InvokeMethod(value2, "SetMainText", new object[1] { "Potential Dealer\n" + customFullName }); DebugLog.Msg("Updated PotentialDealerPoI for " + iD); } } } catch (Exception ex) { DebugLog.Error("Error refreshing dealer POIs: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static string GetUpdatedPoiText(object npc, string currentText) { string customFullName = NpcNameManager.GetCustomFullName(npc); if (string.IsNullOrEmpty(customFullName)) { return null; } if (currentText.EndsWith("\n(Dealer)")) { return customFullName + "\n(Dealer)"; } if (currentText.StartsWith("Potential Dealer\n")) { return "Potential Dealer\n" + customFullName; } if (currentText.StartsWith("Potential Customer\n")) { return "Potential Customer\n" + customFullName; } if (currentText.StartsWith("Supplier Meeting\n(") && currentText.EndsWith(")")) { return "Supplier Meeting\n(" + customFullName + ")"; } if (currentText.EndsWith("'s Stash")) { return customFullName + "'s Stash"; } string firstName = NpcAccess.GetFirstName(npc); string lastName = NpcAccess.GetLastName(npc); string text = (NpcAccess.GetHasLastName(npc) ? (firstName + " " + lastName) : firstName); if (currentText.Contains(text)) { return currentText.Replace(text, customFullName); } return null; } } public static class NpcFieldModifier { private struct OriginalName { public string FirstName; public string LastName; public bool HasLastName; } private static Dictionary<string, OriginalName> _originalNames = new Dictionary<string, OriginalName>(); public static void ApplyAllCustomNames() { if (!Config.Enabled) { return; } try { Type nPC = GameTypes.NPC; if (nPC == null) { DebugLog.Error("[NpcFieldModifier] Could not resolve NPC type"); return; } Object[] array = GameTypes.FindObjectsOfType(nPC); DebugLog.Msg($"[NpcFieldModifier] Found {array.Length} NPCs in scene"); int num = 0; Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null) && ApplyCustomName(val)) { num++; } } if (num > 0) { DebugLog.Msg($"Applied custom names to {num} NPCs"); } } catch (Exception ex) { DebugLog.Error("Error applying custom names: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } public static bool ApplyCustomName(object npc) { if (npc == null) { return false; } string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { return false; } if (!NpcNameManager.HasCustomName(iD)) { return false; } NpcNameManager.CustomName customName = NpcNameManager.GetCustomName(iD); if (!_originalNames.ContainsKey(iD)) { _originalNames[iD] = new OriginalName { FirstName = NpcAccess.GetFirstName(npc), LastName = NpcAccess.GetLastName(npc), HasLastName = NpcAccess.GetHasLastName(npc) }; } NpcAccess.SetFirstName(npc, customName.FirstName); NpcAccess.SetLastName(npc, customName.LastName); NpcAccess.SetHasLastName(npc, customName.HasLastName); string firstName = NpcAccess.GetFirstName(npc); if (firstName != customName.FirstName) { DebugLog.Warning("[NpcFieldModifier] SetFirstName may have failed for " + iD + ": expected '" + customName.FirstName + "', got '" + firstName + "'"); } DebugLog.Msg("Applied custom name to " + iD + ": " + customName.FirstName + " " + customName.LastName); return true; } public static void RestoreOriginalName(object npc) { if (npc != null) { string iD = NpcAccess.GetID(npc); if (!string.IsNullOrEmpty(iD) && _originalNames.TryGetValue(iD, out var value)) { NpcAccess.SetFirstName(npc, value.FirstName); NpcAccess.SetLastName(npc, value.LastName); NpcAccess.SetHasLastName(npc, value.HasLastName); _originalNames.Remove(iD); DebugLog.Msg("Restored original name for " + iD); } } } public static void Reset() { _originalNames.Clear(); } } public static class MessagingNameRefresher { public static void RefreshAllConversations() { if (!Config.Enabled) { return; } try { Type messagesApp = GameTypes.MessagesApp; if (messagesApp == null) { DebugLog.Msg("MessagesApp type not resolved"); return; } if (!GameSingletons.PlayerSingletonExists(messagesApp)) { DebugLog.Msg("MessagesApp not available yet"); return; } object playerSingleton = GameSingletons.GetPlayerSingleton(messagesApp); if (playerSingleton == null) { DebugLog.Msg("MessagesApp instance is null"); return; } IEnumerable conversations = GetConversations(messagesApp, playerSingleton); if (conversations == null) { DebugLog.Msg("Conversations list is null"); return; } int num = 0; foreach (object item in conversations) { if (item == null) { continue; } object value = ReflectionHelper.GetValue(item, "sender"); if (value != null) { string iD = NpcAccess.GetID(value); if (!string.IsNullOrEmpty(iD) && NpcNameManager.HasCustomName(iD)) { NpcNameManager.CustomName customName = NpcNameManager.GetCustomName(iD); string text = (customName.HasLastName ? (customName.FirstName + " " + customName.LastName) : customName.FirstName); ReflectionHelper.SetValue(item, "contactName", text); UpdateConversationEntryUI(item, text, playerSingleton); num++; DebugLog.Msg("Updated conversation contactName for " + iD + ": " + text); } } } if (num > 0) { DebugLog.Msg($"Refreshed {num} conversation contact names"); } } catch (Exception ex) { DebugLog.Error("Error refreshing conversation names: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } public static void RefreshNpcConversation(object npc) { if (!Config.Enabled || npc == null) { return; } try { string iD = NpcAccess.GetID(npc); if (string.IsNullOrEmpty(iD)) { return; } DebugLog.Msg("RefreshNpcConversation: Refreshing for " + iD); Type messagesApp = GameTypes.MessagesApp; if (messagesApp == null) { DebugLog.Msg("RefreshNpcConversation: MessagesApp type not resolved"); return; } if (!GameSingletons.PlayerSingletonExists(messagesApp)) { DebugLog.Msg("RefreshNpcConversation: MessagesApp singleton not available"); return; } object playerSingleton = GameSingletons.GetPlayerSingleton(messagesApp); if (playerSingleton == null) { DebugLog.Msg("RefreshNpcConversation: MessagesApp instance is null"); return; } IEnumerable conversations = GetConversations(messagesApp, playerSingleton); if (conversations == null) { DebugLog.Msg("RefreshNpcConversation: Conversations list is null"); return; } foreach (object item in conversations) { if (item == null) { continue; } object value = ReflectionHelper.GetValue(item, "sender"); if (value == null) { continue; } string iD2 = NpcAccess.GetID(value); if (iD2 != iD) { continue; } string text; if (NpcNameManager.HasCustomName(iD)) { NpcNameManager.CustomName customName = NpcNameManager.GetCustomName(iD); text = (customName.HasLastName ? (customName.FirstName + " " + customName.LastName) : customName.FirstName); } else { text = NpcAccess.GetFullName(npc); } ReflectionHelper.SetValue(item, "contactName", text); UpdateConversationEntryUI(item, text, playerSingleton); DebugLog.Msg("Updated conversation for " + iD + ": " + text); break; } } catch (Exception ex) { DebugLog.Error("Error refreshing NPC conversation: " + ex.Message); DebugLog.Error("Stack trace: " + ex.StackTrace); } } private static IEnumerable GetConversations(Type messagesAppType, object messagesApp) { object obj = null; obj = ReflectionHelper.GetStaticValue(messagesAppType, "Conversations"); if (obj == null && messagesApp != null) { Type type = messagesApp.GetType(); obj = ReflectionHelper.GetStaticValue(type, "Conversations"); } if (obj == null && messagesApp != null) { obj = ReflectionHelper.GetValue(messagesApp, "Conversations"); } if (obj == null) { DebugLog.Msg("GetConversations: Could not retrieve Conversations from any source"); return null; } if (obj is IEnumerable result) { return result; } DebugLog.Msg("GetConversations: List type " + obj.GetType().FullName + " is not IEnumerable, using Count/indexer"); return IterateViaReflection(obj); } private static IEnumerable IterateViaReflection(object list) { try { Type type = list.GetType(); PropertyInfo property = type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public); if (property == null) { DebugLog.Msg("IterateViaReflection: No Count property found"); return null; } int num = (int)property.GetValue(list); PropertyInfo property2 = type.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public); if (property2 == null) { MethodInfo method = type.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public); if (method == null) { DebugLog.Msg("IterateViaReflection: No Item property or get_Item method found"); return null; } List<object> list2 = new List<object>(num); for (int i = 0; i < num; i++) { list2.Add(method.Invoke(list, new object[1] { i })); } return list2; } List<object> list3 = new List<object>(num); for (int j = 0; j < num; j++) { list3.Add(property2.GetValue(list, new object[1] { j })); } DebugLog.Msg($"IterateViaReflection: Collected {num} conversations"); return list3; } catch (Exception ex) { DebugLog.Error("IterateViaReflection failed: " + ex.Message); return null; } } private static void UpdateConversationEntryUI(object conversation, string newName, object messagesApp) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) try { object value = ReflectionHelper.GetValue(conversation, "entry"); RectTransform val = null; RectTransform val2 = (RectTransform)((value is RectTransform) ? value : null); if (val2 != null) { val = val2; } else { Transform val3 = (Transform)((value is Transform) ? value : null); if (val3 != null) { val = ((Component)val3).GetComponent<RectTransform>(); } else { Component val4 = (Component)((value is Component) ? value : null); if (val4 != null) { val = val4.GetComponent<RectTransform>(); } } } if ((Object)(object)val != (Object)null) { Transform val5 = ((Transform)val).Find("Name"); if ((Object)(object)val5 != (Object)null) { Text component = ((Component)val5).GetComponent<Text>(); object value2 = ReflectionHelper.GetValue(conversation, "IsSenderKnown"); bool flag = default(bool); int num; if (value2 is bool) { flag = (bool)value2; num = 1; } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; if ((Object)(object)component != (Object)null && flag2) { component.text = newName; Canvas.ForceUpdateCanvases(); Transform val6 = ((Transform)val).Find("Category"); if ((Object)(object)val6 != (Object)null && ((Component)val6).gameObject.activeSelf) { RectTransform component2 = ((Component)val6).GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null) { Vector2 anchoredPosition = component2.anchoredPosition; anchoredPosition.x = 225f + component.preferredWidth; component2.anchoredPosition = anchoredPosition; } } } } } object value3 = ReflectionHelper.GetValue(conversation, "isOpen"); bool flag3 = default(bool); int num2; if (value3 is bool) { flag3 = (bool)value3; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag3 ? 1u : 0u)) == 0 || messagesApp == null) { return; } object value4 = ReflectionHelper.GetValue(messagesApp, "dialoguePageNameText"); Text val7 = (Text)((value4 is Text) ? value4 : null); if ((Object)(object)val7 != (Object)null) { object value5 = ReflectionHelper.GetValue(conversation, "IsSenderKnown"); bool flag4 = default(bool); int num3; if (value5 is bool) { flag4 = (bool)value5; num3 = 1; } else { num3 = 0; } if (((uint)num3 & (flag4 ? 1u : 0u)) != 0) { val7.text = newName; } } } catch (Exception ex) { DebugLog.Error("Error updating conversation entry UI: " + ex.Message); } } } } namespace RenameNPCs.Utils { public static class Constants { public static class Game { public const string GAME_STUDIO = "TVGS"; public const string GAME_NAME = "Schedule I"; } public static class Prefs { public const string CATEGORY_SETTINGS = "RenameNPCs"; public const string CATEGORY_NAMES = "RenameNPCs_Names"; public const string NAME_SEPARATOR = "|"; } public static class Input { public const float HOLD_DURATION = 0.5f; public const float MAX_RAYCAST_RANGE = 5f; } public const string MOD_NAME = "RenameNPCs"; public const string MOD_VERSION = "1.0.0"; public const string MOD_AUTHOR = "HazDS"; } public static class DebugLog { public static void Msg(string message) { if (Config.DebugLogsEnabled) { Melon<Core>.Logger.Msg(message); } } public static void Warning(string message) { Melon<Core>.Logger.Warning(message); } public static void Error(string message) { Melon<Core>.Logger.Error(message); } } public static class GameTypes { private static bool? _isIl2Cpp; private static Assembly _gameAssembly; private static Type _npc; private static Type _dealer; private static Type _customer; private static Type _npcPoI; private static Type _customerSelector; private static Type _textInputScreen; private static Type _playerCamera; private static Type _messagesApp; private static Type _msgConversation; private static Type _phone; private static Type _interactionManager; public static bool IsIl2Cpp { get { if (!_isIl2Cpp.HasValue) { _isIl2Cpp = Type.GetType("Il2CppScheduleOne.NPCs.NPC, Assembly-CSharp") != null; } return _isIl2Cpp.Value; } } private static string Prefix => IsIl2Cpp ? "Il2CppScheduleOne" : "ScheduleOne"; private static Assembly GameAssembly { get { if (_gameAssembly == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "Assembly-CSharp") { _gameAssembly = assembly; break; } } } return _gameAssembly; } } public static Type NPC => _npc ?? (_npc = Resolve("NPCs.NPC")); public static Type Dealer => _dealer ?? (_dealer = Resolve("Economy.Dealer")); public static Type Customer => _customer ?? (_customer = Resolve("Economy.Customer")); public static Type NPCPoI => _npcPoI ?? (_npcPoI = Resolve("Map.NPCPoI")); public static Type CustomerSelector => _customerSelector ?? (_customerSelector = Resolve("UI.Phone.CustomerSelector")); public static Type TextInputScreen => _textInputScreen ?? (_textInputScreen = Resolve("UI.TextInputScreen")); public static Type PlayerCamera => _playerCamera ?? (_playerCamera = Resolve("PlayerScripts.PlayerCamera")); public static Type MessagesApp => _messagesApp ?? (_messagesApp = Resolve("UI.Phone.Messages.MessagesApp")); public static Type MSGConversation => _msgConversation ?? (_msgConversation = Resolve("Messaging.MSGConversation")); public static Type Phone => _phone ?? (_phone = Resolve("UI.Phone.Phone")); public static Type InteractionManager => _interactionManager ?? (_interactionManager = Resolve("Interaction.InteractionManager")); public static Type Resolve(string relativeTypeName) { string name = Prefix + "." + relativeTypeName; return GameAssembly?.GetType(name); } public static Type ResolveRoot(string typeName) { string name = Prefix + "." + typeName; return GameAssembly?.GetType(name); } public static Object[] FindObjectsOfType(Type type) { try { MethodInfo[] methods = typeof(Object).GetMethods(BindingFlags.Static | BindingFlags.Public); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo.Name != "FindObjectsOfType" || methodInfo.IsGenericMethod) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 1) { continue; } Type parameterType = parameters[0].ParameterType; object obj; if (parameterType == typeof(Type)) { obj = type; } else { DebugLog.Msg("FindObjectsOfType: IL2CPP path, param type is " + parameterType.FullName); Type type2 = Type.GetType("Il2CppInterop.Runtime.Il2CppType, Il2CppInterop.Runtime"); if (type2 == null) { DebugLog.Error("FindObjectsOfType: Could not find Il2CppType class"); return (Object[])(object)new Object[0]; } MethodInfo method = type2.GetMethod("From", new Type[1] { typeof(Type) }); if (method == null) { DebugLog.Error("FindObjectsOfType: Could not find Il2CppType.From method"); return (Object[])(object)new Object[0]; } obj = method.Invoke(null, new object[1] { type }); if (obj == null) { DebugLog.Error("FindObjectsOfType: Il2CppType.From(" + type.FullName + ") returned null"); return (Object[])(object)new Object[0]; } DebugLog.Msg("FindObjectsOfType: Converted type to " + obj.GetType().FullName); } object obj2 = methodInfo.Invoke(null, new object[1] { obj }); if (obj2 == null) { DebugLog.Msg("FindObjectsOfType(" + type.Name + "): result was null"); return (Object[])(object)new Object[0]; } if (obj2 is Object[] result) { return result; } DebugLog.Msg("FindObjectsOfType(" + type.Name + "): result type is " + obj2.GetType().FullName + ", trying IEnumerable"); if (obj2 is IEnumerable enumerable) { List<Object> list = new List<Object>(); foreach (object item in enumerable) { Object val = (Object)((item is Object) ? item : null); if (val != null) { list.Add(val); } } DebugLog.Msg($"FindObjectsOfType({type.Name}): collected {list.Count} objects via IEnumerable"); return list.ToArray(); } DebugLog.Msg("FindObjectsOfType(" + type.Name + "): result is not IEnumerable"); return (Object[])(object)new Object[0]; } } catch (Exception ex) { DebugLog.Error("FindObjectsOfType failed: " + ex.Message); } return (Object[])(object)new Object[0]; } public static Component GetComponentInParent(Component component, Type type) { try { MethodInfo[] methods = typeof(Component).GetMethods(BindingFlags.Instance | BindingFlags.Public); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (methodInfo.Name != "GetComponentInParent" || methodInfo.IsGenericMethod) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 1) { continue; } Type parameterType = parameters[0].ParameterType; object obj; if (parameterType == typeof(Type)) { obj = type; } else { Type type2 = Type.GetType("Il2CppInterop.Runtime.Il2CppType, Il2CppInterop.Runtime"); if (type2 == null) { return null; } obj = type2.GetMethod("From", new Type[1] { typeof(Type) })?.Invoke(null, new object[1] { type }); if (obj == null) { return null; } } object? obj2 = methodInfo.Invoke(component, new object[1] { obj }); return (Component)((obj2 is Component) ? obj2 : null); } } catch (Exception ex) { DebugLog.Error("GetComponentInParent failed: " + ex.Message); } return null; } public static Type GetSingletonType(Type innerType) { return Resolve("DevUtilities.Singleton`1")?.MakeGenericType(innerType); } public static Type GetPlayerSingletonType(Type innerType) { return Resolve("DevUtilities.PlayerSingleton`1")?.MakeGenericType(innerType); } } public static class NpcAccess { private static FieldInfo _firstNameField; private static PropertyInfo _firstNameProperty; private static FieldInfo _lastNameField; private static PropertyInfo _lastNameProperty; private static FieldInfo _hasLastNameField; private static PropertyInfo _hasLastNameProperty; private static FieldInfo _idField; private static PropertyInfo _idProperty; private static PropertyInfo _fullNameProperty; private static FieldInfo _regionField; private static PropertyInfo _regionProperty; private static bool _fieldsResolved; private static void EnsureResolved() { if (_fieldsResolved) { return; } _fieldsResolved = true; Type nPC = GameTypes.NPC; if (nPC == null) { DebugLog.Error("[NpcAccess] Could not resolve NPC type"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; _firstNameField = nPC.GetField("FirstName", bindingAttr); _firstNameProperty = nPC.GetProperty("FirstName", bindingAttr); _lastNameField = nPC.GetField("LastName", bindingAttr); _lastNameProperty = nPC.GetProperty("LastName", bindingAttr); _hasLastNameField = nPC.GetField("hasLastName", bindingAttr); _hasLastNameProperty = nPC.GetProperty("hasLastName", bindingAttr); _idField = nPC.GetField("ID", bindingAttr); _idProperty = nPC.GetProperty("ID", bindingAttr); _fullNameProperty = nPC.GetProperty("fullName", bindingAttr); _regionField = nPC.GetField("Region", bindingAttr); _regionProperty = nPC.GetProperty("Region", bindingAttr); bool flag = _firstNameField != null || _firstNameProperty != null; bool flag2 = _idField != null || _idProperty != null; if (!flag) { DebugLog.Warning("[NpcAccess] Could not find FirstName field or property"); } if (!flag2) { DebugLog.Warning("[NpcAccess] Could not find ID field or property"); } DebugLog.Msg("[NpcAccess] Resolved: FirstName=" + ((_firstNameField != null) ? "field" : ((_firstNameProperty != null) ? "property" : "MISSING")) + ", ID=" + ((_idField != null) ? "field" : ((_idProperty != null) ? "property" : "MISSING"))); } public static string GetID(object npc) { if (npc == null) { return null; } EnsureResolved(); try { if (_idProperty != null) { return _idProperty.GetValue(npc) as string; } if (_idField != null) { return _idField.GetValue(npc) as string; } } catch { } return null; } public static string GetFirstName(object npc) { if (npc == null) { return null; } EnsureResolved(); try { if (_firstNameField != null) { return _firstNameField.GetValue(npc) as string; } if (_firstNameProperty != null) { return _firstNameProperty.GetValue(npc) as string; } } catch { } return null; } public static string GetLastName(object npc) { if (npc == null) { return null; } EnsureResolved(); try { if (_lastNameField != null) { return _lastNameField.GetValue(npc) as string; } if (_lastNameProperty != null) { return _lastNameProperty.GetValue(npc) as string; } } catch { } return null; } public static bool GetHasLastName(object npc) { if (npc == null) { return false; } EnsureResolved(); try { object obj = null; if (_hasLastNameField != null) { obj = _hasLastNameField.GetValue(npc); } else if (_hasLastNameProperty != null) { obj = _hasLastNameProperty.GetValue(npc); } bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { } return false; } public static string GetFullName(object npc) { if (npc == null) { return null; } EnsureResolved(); try { return _fullNameProperty?.GetValue(npc) as string; } catch { } string firstName = GetFirstName(npc); if (GetHasLastName(npc)) { return firstName + " " + GetLastName(npc); } return firstName; } public static string GetRegion(object npc) { if (npc == null) { return null; } EnsureResolved(); try { object obj = null; if (_regionField != null) { obj = _regionField.GetValue(npc); } else if (_regionProperty != null) { obj = _regionProperty.GetValue(npc); } return obj?.ToString(); } catch { } return null; } public static void SetFirstName(object npc, string value) { if (npc == null) { return; } EnsureResolved(); try { if (_firstNameField != null) { _firstNameField.SetValue(npc, value); } else if (_firstNameProperty != null) { _firstNameProperty.SetValue(npc, value); } } catch (Exception ex) { DebugLog.Error("[NpcAccess] SetFirstName failed: " + ex.Message); } } public static void SetLastName(object npc, string value) { if (npc == null) { return; } EnsureResolved(); try { if (_lastNameField != null) { _lastNameField.SetValue(npc, value); } else if (_lastNameProperty != null) { _lastNameProperty.SetValue(npc, value); } } catch (Exception ex) { DebugLog.Error("[NpcAccess] SetLastName failed: " + ex.Message); } } public static void SetHasLastName(object npc, bool value) { if (npc == null) { return; } EnsureResolved(); try { if (_hasLastNameField != null) { _hasLastNameField.SetValue(npc, value); } else if (_hasLastNameProperty != null) { _hasLastNameProperty.SetValue(npc, value); } } catch (Exception ex) { DebugLog.Error("[NpcAccess] SetHasLastName failed: " + ex.Message); } } public static bool IsNpc(object obj) { if (obj == null) { return false; } Type nPC = GameTypes.NPC; return nPC != null && nPC.IsInstanceOfType(obj); } public static bool IsDealer(object npc) { if (npc == null) { return false; } Type dealer = GameTypes.Dealer; return dealer != null && dealer.IsInstanceOfType(npc); } } public static class GameSingletons { public static object GetSingleton(Type innerType) { try { Type singletonType = GameTypes.GetSingletonType(innerType); if (singletonType == null) { return null; } return singletonType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); } catch { return null; } } public static bool SingletonExists(Type innerType) { try { Type singletonType = GameTypes.GetSingletonType(innerType); if (singletonType == null) { return false; } object obj = singletonType.GetProperty("InstanceExists", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } public static object GetPlayerSingleton(Type innerType) { try { Type playerSingletonType = GameTypes.GetPlayerSingletonType(innerType); if (playerSingletonType == null) { return null; } return playerSingletonType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); } catch { return null; } } public static bool PlayerSingletonExists(Type innerType) { try { Type playerSingletonType = GameTypes.GetPlayerSingletonType(innerType); if (playerSingletonType == null) { return false; } object obj = playerSingletonType.GetProperty("InstanceExists", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } } public static class ReflectionHelper { private static readonly BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public; private static readonly BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy; public static object GetValue(object instance, string memberName) { if (instance == null) { return null; } Type type = instance.GetType(); try { PropertyInfo property = type.GetProperty(memberName, InstanceFlags); if (property != null) { return property.GetValue(instance); } FieldInfo field = type.GetField(memberName, InstanceFlags); if (field != null) { return field.GetValue(instance); } } catch (Exception ex) { DebugLog.Error("[ReflectionHelper] GetValue(" + type.Name + "." + memberName + ") failed: " + ex.Message); } return null; } public static void SetValue(object instance, string memberName, object value) { if (instance == null) { return; } Type type = instance.GetType(); try { PropertyInfo property = type.GetProperty(memberName, InstanceFlags); if (property != null && property.CanWrite) { property.SetValue(instance, value); return; } FieldInfo field = type.GetField(memberName, InstanceFlags); if (field != null) { field.SetValue(instance, value); } } catch (Exception ex) { DebugLog.Error("[ReflectionHelper] SetValue(" + type.Name + "." + memberName + ") failed: " + ex.Message); } } public static object InvokeMethod(object instance, string methodName, object[] args = null) { if (instance == null) { return null; } Type type = instance.GetType(); try { MethodInfo method = type.GetMethod(methodName, InstanceFlags); if (method != null) { return method.Invoke(instance, args); } } catch (Exception ex) { DebugLog.Error("[ReflectionHelper] InvokeMethod(" + type.Name + "." + methodName + ") failed: " + ex.Message); } return null; } public static object GetStaticValue(Type type, string memberName) { if (type == null) { return null; } try { PropertyInfo property = type.GetProperty(memberName, StaticFlags); if (property != null) { return property.GetValue(null); } FieldInfo field = type.GetField(memberName, StaticFlags); if (field != null) { return field.GetValue(null); } } catch (Exception ex) { DebugLog.Error("[ReflectionHelper] GetStaticValue(" + type.Name + "." + memberName + ") failed: " + ex.Message); } return null; } } }