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 3 weeks 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; } } }