Decompiled source of RenameNPCs v1.0.0

RenameNPCs.dll

Decompiled 18 hours ago
using 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;
		}
	}
}