using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WhereIsThing")] [assembly: AssemblyDescription("Shows the live locations of selected dropped items in PEAK.")] [assembly: AssemblyProduct("WhereIsThing")] [assembly: ComVisible(false)] [assembly: Guid("f9d08f85-c8c7-4b51-97f9-f3a2f32f6f8a")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.1.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WhereIsThing { internal static class FontHelper { private const string ChineseSample = "物品在哪简体中文急救箱绷带药用根茎灵药菇"; private static TMP_FontAsset _cached; public static TMP_FontAsset GetChineseCapable() { if (IsChineseCapable(_cached)) { return _cached; } try { TMP_FontAsset val = FindPreferredFont(); if ((Object)(object)val != (Object)null) { _cached = val; return val; } } catch { } return null; } public static void InvalidateCache() { _cached = null; } public static bool IsChineseCapable(TMP_FontAsset font) { return IsChineseCapable(font, new HashSet()); } public static TMP_FontAsset GetLabelFont(ThingLabelFont choice) { string source; TMP_FontAsset val = GetFontForChoice(choice, out source); if ((Object)(object)val == (Object)null) { val = GetGameDefaultFont(); } return val; } private static bool IsChineseCapable(TMP_FontAsset font, HashSet visited) { if ((Object)(object)font == (Object)null || !visited.Add(font)) { return false; } try { if (font.HasCharacters("物品在哪简体中文急救箱绷带药用根茎灵药菇")) { return true; } } catch { } if (font.fallbackFontAssetTable == null) { return false; } foreach (TMP_FontAsset item in font.fallbackFontAssetTable) { if ((Object)(object)item != (Object)null && item != font && IsChineseCapable(item, visited)) { return true; } } return false; } private static TMP_FontAsset FindPreferredFont() { TMP_FontAsset[] candidateFonts = GetCandidateFonts(); foreach (TMP_FontAsset val in candidateFonts) { if (IsChineseCapable(val)) { return val; } } candidateFonts = GetCandidateFonts(); foreach (TMP_FontAsset val2 in candidateFonts) { if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } private static TMP_FontAsset GetFontForChoice(ThingLabelFont choice, out string source) { switch (choice) { case ThingLabelFont.TmpDefault: source = "TmpDefault"; return TMP_Settings.defaultFontAsset; case ThingLabelFont.KoreanBinggrae: source = "KoreanBinggrae"; return FindFontAsset("Korean Binggrae-Bold SDF"); case ThingLabelFont.Crazk: source = "Crazk"; return FindFontAsset("CRAZK___ SDF"); case ThingLabelFont.Auto: source = "Auto(GameDefault)"; return GetGameDefaultFont() ?? TMP_Settings.defaultFontAsset; default: source = "GameDefault"; return GetGameDefaultFont(); } } private static TMP_FontAsset GetGameDefaultFont() { if (!((Object)(object)FontFallbackSwapper.instance == (Object)null)) { return FontFallbackSwapper.instance.mainBaseFont; } return null; } private static TMP_FontAsset FindFontAsset(string assetName) { IEnumerable first = Resources.FindObjectsOfTypeAll(); IEnumerable second; try { second = Resources.LoadAll(string.Empty); } catch { second = Enumerable.Empty(); } return (from font in first.Concat(second) where (Object)(object)font != (Object)null select font).Distinct().FirstOrDefault((Func)((TMP_FontAsset font) => string.Equals(NormalizeFontName(((Object)font).name), NormalizeFontName(assetName), StringComparison.OrdinalIgnoreCase))); } private static string NormalizeFontName(string name) { if (string.IsNullOrEmpty(name)) { return string.Empty; } int num = name.IndexOf(" (Clone)", StringComparison.OrdinalIgnoreCase); return ((num < 0) ? name : name.Substring(0, num)).Trim(); } private static TMP_FontAsset[] GetCandidateFonts() { List list = new List(); TMP_FontAsset gameDefaultFont = GetGameDefaultFont(); if ((Object)(object)gameDefaultFont != (Object)null) { list.Add(gameDefaultFont); } TextMeshProUGUI val = Object.FindAnyObjectByType(); if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null) { list.Add(((TMP_Text)val).font); } if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { list.Add(TMP_Settings.defaultFontAsset); } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val2 in array) { if ((Object)(object)val2 != (Object)null) { list.Add(val2); } } return list.Distinct().ToArray(); } } internal static class ModConfigLocalization { private const string ModConfigGuid = "com.github.PEAKModding.PEAKLib.ModConfig"; private const string ConfigFileName = "com.wuyachiyu.WhereIsThing.cfg"; private static readonly FieldInfo DescriptionBackingField = typeof(ConfigDescription).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); private static Type _tmpTextType; private static PropertyInfo _tmpTextProperty; private static bool IsChinese { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((int)LocalizedText.CURRENT_LANGUAGE != 9) { return (int)LocalizedText.CURRENT_LANGUAGE == 10; } return true; } } public static void PatchDisplayNames(Harmony harmony) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown if (harmony == null || !Chainloader.PluginInfos.TryGetValue("com.github.PEAKModding.PEAKLib.ModConfig", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return; } Assembly assembly = ((object)value.Instance).GetType().Assembly; HarmonyMethod val = new HarmonyMethod(typeof(ModConfigLocalization).GetMethod("ModConfigDisplayNamePostfix", BindingFlags.Static | BindingFlags.NonPublic)); Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (!(type == null) && !type.IsAbstract && !type.IsInterface && type.FullName != null && type.FullName.StartsWith("PEAKLib.ModConfig.SettingOptions.BepInEx", StringComparison.Ordinal)) { MethodInfo methodInfo = AccessTools.Method(type, "GetDisplayName", Type.EmptyTypes, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } Type type2 = assembly.GetType("PEAKLib.ModConfig.Components.ModdedSettingsMenu"); if (type2 == null) { return; } HarmonyMethod val2 = new HarmonyMethod(typeof(ModConfigLocalization).GetMethod("ModConfigUiChangedPostfix", BindingFlags.Static | BindingFlags.NonPublic)); string[] array = new string[4] { "OnEnable", "ShowSettings", "SetSection", "UpdateSectionTabs" }; foreach (string methodName in array) { MethodInfo methodInfo2 = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo candidate) => candidate.Name == methodName); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } public static void ApplyLocalizedDescriptions(IEnumerable entries) { if (entries == null) { return; } foreach (ConfigEntryBase item in entries.Where((ConfigEntryBase entry) => entry != null)) { SetDescription(item, GetLocalizedDescription(item.Definition.Key)); } } private static void ModConfigDisplayNamePostfix(object __instance, ref string __result) { ConfigEntryBase val = TryGetConfigEntry(__instance); if (IsWhereIsThingEntry(val)) { string localizedConfigText = GetLocalizedConfigText(val.Definition.Section, val.Definition.Key); if (!string.IsNullOrEmpty(localizedConfigText)) { __result = localizedConfigText; } } } private static void ModConfigUiChangedPostfix(MonoBehaviour __instance) { if ((Object)(object)__instance != (Object)null) { __instance.StartCoroutine(LocalizeModConfigUiDeferred(((Component)__instance).transform)); } } private static IEnumerator LocalizeModConfigUiDeferred(Transform root) { yield return null; LocalizeTextInHierarchy(root); } private static void LocalizeTextInHierarchy(Transform root) { if ((Object)(object)root == (Object)null) { return; } try { EnsureTmpReflection(); if (_tmpTextType == null || _tmpTextProperty == null) { return; } Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(_tmpTextType, true); foreach (Component obj in componentsInChildren) { string text = _tmpTextProperty.GetValue(obj, null) as string; string localizedUiText = GetLocalizedUiText(text); if (!string.IsNullOrEmpty(localizedUiText) && localizedUiText != text) { _tmpTextProperty.SetValue(obj, localizedUiText, null); } } } catch { } } private static void EnsureTmpReflection() { if (_tmpTextType != null) { return; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { _tmpTextType = assemblies[i].GetType("TMPro.TextMeshProUGUI"); if (_tmpTextType != null) { _tmpTextProperty = _tmpTextType.GetProperty("text"); break; } } } private static string GetLocalizedUiText(string text) { if (string.IsNullOrWhiteSpace(text)) { return null; } string text2 = text.Replace(" ", string.Empty); string localizedToken = GetLocalizedToken(GetCanonicalToken(text2)); if (!string.IsNullOrEmpty(localizedToken)) { return localizedToken; } if (text2.IndexOf(',') >= 0) { string[] array = text2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(GetCanonicalToken).Select(GetLocalizedToken) .ToArray(); if (array.All((string value) => !string.IsNullOrEmpty(value))) { return string.Join(IsChinese ? "、" : ", ", array); } } return null; } private static string GetLocalizedConfigText(string section, string key) { string canonicalToken = GetCanonicalToken((section == null) ? string.Empty : section.Replace(" ", string.Empty)); string canonicalToken2 = GetCanonicalToken((key == null) ? string.Empty : key.Replace(" ", string.Empty)); if (string.IsNullOrEmpty(canonicalToken2)) { return null; } if (!IsKnownConfigKey(canonicalToken, canonicalToken2)) { return null; } return GetLocalizedToken(canonicalToken2); } private static bool IsKnownConfigKey(string section, string key) { switch (section) { case "General": switch (key) { default: return key == "DisplayDurationSeconds"; case "Enabled": case "ScanKey": case "WindowKey": case "ScanMode": return true; } case "Display": switch (key) { default: return key == "ShowOffscreenDirection"; case "NameLanguage": case "MaxDistance": case "FontSize": case "LabelFont": return true; } case "Presets": switch (key) { default: return key == "ShareMode"; case "PresetSchemaVersion": case "LocalPresets": case "ActiveLocalPresetId": case "SelectedSharedPresetId": return true; } case "Selection": switch (key) { default: return key == "LocationScopes"; case "SelectedItemIds": case "SelectedLuggage": case "SelectedLuggageTypes": case "SelectedSceneTargetTypes": return true; } default: return false; } } private static string GetCanonicalToken(string value) { if (string.IsNullOrEmpty(value)) { return null; } return value switch { "物品在哪" => "WhereIsThing", "常规" => "General", "显示" => "Display", "选择" => "Selection", "预设" => "Presets", "启用MOD" => "Enabled", "扫描快捷键" => "ScanKey", "选择窗口快捷键" => "WindowKey", "显示模式" => "ScanMode", "定时显示秒数" => "DisplayDurationSeconds", "名称语言" => "NameLanguage", "最大距离" => "MaxDistance", "标签字号" => "FontSize", "标签字体" => "LabelFont", "屏外方向提示" => "ShowOffscreenDirection", "已选物品ID" => "SelectedItemIds", "兼容行李箱开关" => "SelectedLuggage", "已选行李箱类型" => "SelectedLuggageTypes", "已选场景目标" => "SelectedSceneTargetTypes", "位置范围" => "LocationScopes", "预设版本号" => "PresetSchemaVersion", "本地预设数据" => "LocalPresets", "当前本地预设" => "ActiveLocalPresetId", "当前共享预设" => "SelectedSharedPresetId", "房主共享模式" => "ShareMode", "常驻" => "Persistent", "定时" => "Timed", "关闭" => "Off", "仅默认预设" => "BuiltInOnly", "已发布预设" => "PublishedPresets", "跟随游戏" => "Game", "简体中文" => "SimplifiedChinese", "自动" => "Auto", "游戏默认" => "GameDefault", "TMP默认字体" => "TmpDefault", "无" => "None", "地面" => "Ground", "手持" => "Held", "背包" => "Backpack", "行李箱" => "Luggage", _ => value, }; } private static string GetLocalizedToken(string key) { bool isChinese = IsChinese; switch (key) { case "WhereIsThing": if (!isChinese) { return "WhereIsThing"; } return "物品在哪"; case "General": if (!isChinese) { return "General"; } return "常规"; case "Display": if (!isChinese) { return "Display"; } return "显示"; case "Selection": if (!isChinese) { return "Selection"; } return "选择"; case "Presets": if (!isChinese) { return "Presets"; } return "预设"; case "Enabled": if (!isChinese) { return "Enabled"; } return "启用 MOD"; case "ScanKey": if (!isChinese) { return "Scan Key"; } return "扫描快捷键"; case "WindowKey": if (!isChinese) { return "Window Key"; } return "选择窗口快捷键"; case "ScanMode": if (!isChinese) { return "Display Mode"; } return "显示模式"; case "DisplayDurationSeconds": if (!isChinese) { return "Display Duration"; } return "定时显示秒数"; case "NameLanguage": if (!isChinese) { return "Name Language"; } return "名称语言"; case "MaxDistance": if (!isChinese) { return "Max Distance"; } return "最大距离"; case "FontSize": if (!isChinese) { return "Label Font Size"; } return "标签字号"; case "LabelFont": if (!isChinese) { return "Label Font"; } return "标签字体"; case "ShowOffscreenDirection": if (!isChinese) { return "Off-screen Direction"; } return "屏外方向提示"; case "SelectedItemIds": if (!isChinese) { return "Selected Item IDs"; } return "已选物品 ID"; case "SelectedLuggage": if (!isChinese) { return "Legacy Luggage Toggle"; } return "兼容行李箱开关"; case "SelectedLuggageTypes": if (!isChinese) { return "Selected Luggage Types"; } return "已选行李箱类型"; case "SelectedSceneTargetTypes": if (!isChinese) { return "Selected Scene Targets"; } return "已选场景目标"; case "LocationScopes": if (!isChinese) { return "Location Scopes"; } return "位置范围"; case "PresetSchemaVersion": if (!isChinese) { return "Preset Schema Version"; } return "预设版本号"; case "LocalPresets": if (!isChinese) { return "Local Presets"; } return "本地预设数据"; case "ActiveLocalPresetId": if (!isChinese) { return "Active Local Preset"; } return "当前本地预设"; case "SelectedSharedPresetId": if (!isChinese) { return "Selected Shared Preset"; } return "当前共享预设"; case "ShareMode": if (!isChinese) { return "Share Mode"; } return "房主共享模式"; case "MushroomZombie": if (!isChinese) { return "Mushroom Zombie"; } return "森蕈僵尸"; case "Beetle": if (!isChinese) { return "Beetle"; } return "甲虫"; case "Scorpion": if (!isChinese) { return "Scorpion"; } return "蝎子"; case "Spider": if (!isChinese) { return "Spider"; } return "蜘蛛"; case "BeeSwarm": if (!isChinese) { return "Bee Swarm"; } return "蜂群"; case "Scoutmaster": if (!isChinese) { return "Scoutmaster"; } return "童军领队"; case "TumbleWeed": if (!isChinese) { return "Tumbleweed"; } return "风滚草"; case "GhostBall": if (!isChinese) { return "Ghost Ball"; } return "鬼球"; case "SpikeTrap": if (!isChinese) { return "Spike Trap"; } return "地刺"; case "Antlion": if (!isChinese) { return "Antlion"; } return "蚁狮"; case "VenusFlyTrap": if (!isChinese) { return "Venus Flytrap"; } return "捕蝇草"; case "Tornado": if (!isChinese) { return "Tornado"; } return "龙卷风"; case "NapberryHypnoOrb": if (!isChinese) { return "Unpicked Napberry"; } return "未摘下的晚安莓"; case "ArrowShooter": if (!isChinese) { return "Arrow Shooter"; } return "箭矢发射器"; case "MovingSawBlade": if (!isChinese) { return "Moving Sawblade"; } return "移动锯刃"; case "SpikeRoller": if (!isChinese) { return "Spike Roller"; } return "滚刺机关"; case "SwingingAxe": if (!isChinese) { return "Swinging Axe"; } return "摆斧机关"; case "GloomBellTower": if (!isChinese) { return "Gloom Bell Tower"; } return "雾沼钟塔"; case "Persistent": if (!isChinese) { return "Persistent"; } return "常驻"; case "Timed": if (!isChinese) { return "Timed"; } return "定时"; case "Off": if (!isChinese) { return "Off"; } return "关闭"; case "BuiltInOnly": if (!isChinese) { return "Built-in Only"; } return "仅默认预设"; case "PublishedPresets": if (!isChinese) { return "Published Presets"; } return "已发布预设"; case "Game": if (!isChinese) { return "Follow Game"; } return "跟随游戏"; case "English": return "English"; case "SimplifiedChinese": if (!isChinese) { return "Simplified Chinese"; } return "简体中文"; case "Auto": if (!isChinese) { return "Auto"; } return "自动"; case "GameDefault": if (!isChinese) { return "Game Default"; } return "游戏默认"; case "TmpDefault": if (!isChinese) { return "TMP Default"; } return "TMP 默认字体"; case "KoreanBinggrae": return "KoreanBinggrae"; case "Crazk": return "Crazk"; case "None": if (!isChinese) { return "None"; } return "无"; case "Ground": if (!isChinese) { return "Ground"; } return "地面"; case "Held": if (!isChinese) { return "Held"; } return "手持"; case "Backpack": if (!isChinese) { return "Backpack"; } return "背包"; case "Luggage": if (!isChinese) { return "Luggage"; } return "行李箱"; case "Statue": if (!isChinese) { return "Statue"; } return "雕像"; default: return null; } } private static string GetLocalizedDescription(string key) { bool isChinese = IsChinese; switch (key) { case "Enabled": if (!isChinese) { return "Enable or disable WhereIsThing."; } return "启用或关闭 WhereIsThing。"; case "ScanKey": if (!isChinese) { return "Key used to show the locations of selected targets."; } return "显示当前已选目标位置的快捷键。"; case "WindowKey": if (!isChinese) { return "Hold Alt and press this key to open the target selection window."; } return "按住 Alt 后使用此键打开物品选择窗口。"; case "ScanMode": if (!isChinese) { return "Keep location labels visible or hide them automatically after a few seconds."; } return "选择位置标签常驻显示,或在数秒后自动隐藏。"; case "DisplayDurationSeconds": if (!isChinese) { return "Number of seconds labels remain visible in Timed mode."; } return "定时模式下标签持续显示的秒数。"; case "NameLanguage": if (!isChinese) { return "Follow the game language for item names, or force English/Simplified Chinese."; } return "物品名称跟随游戏语言,或强制使用英文/简体中文。"; case "MaxDistance": if (!isChinese) { return "Maximum label distance in meters. Set to 0 for unlimited."; } return "显示标签的最大距离,单位米。0 表示不限制。"; case "FontSize": if (!isChinese) { return "Font size used by location and distance labels."; } return "位置与距离标签的字号。"; case "LabelFont": if (!isChinese) { return "Choose a font for English location labels only. Chinese text may display as tofu boxes."; } return "选择仅用于英文位置标签的字体;中文可能显示为口口口。"; case "ShowOffscreenDirection": if (!isChinese) { return "Show a direction indicator when a target is off-screen."; } return "目标在屏幕外时显示方向提示。"; case "SelectedItemIds": if (!isChinese) { return "Item IDs managed by the Alt+C selection window. Do not edit manually."; } return "由 Alt+C 选择窗口维护的物品 ID,请勿手动编辑。"; case "SelectedLuggage": if (!isChinese) { return "Legacy compatibility setting. Choose luggage types in the selection window."; } return "旧版配置兼容项,请使用选择窗口设置行李箱类型。"; case "SelectedLuggageTypes": if (!isChinese) { return "Luggage types managed by the Alt+C selection window. Do not edit manually."; } return "由 Alt+C 选择窗口维护的行李箱类型,请勿手动编辑。"; case "SelectedSceneTargetTypes": if (!isChinese) { return "Scene target types managed by the Alt+C selection window. Do not edit manually."; } return "由 Alt+C 选择窗口维护的动态危险和钟塔类型,请勿手动编辑。"; case "LocationScopes": if (!isChinese) { return "Target location scopes. Statue scope shows selected amulet fragments held by scene statues. Luggage scanning is controlled automatically by the luggage types selected in the Alt+C window."; } return "目标位置范围。雕像范围会显示已选护符在场景雕像手中的碎片;行李箱是否扫描由 Alt+C 窗口中已选的行李箱类型自动控制。"; case "PresetSchemaVersion": if (!isChinese) { return "Internal preset schema version used by WhereIsThing. Do not edit manually."; } return "WhereIsThing 内部使用的预设数据版本,请勿手动编辑。"; case "LocalPresets": if (!isChinese) { return "Serialized local presets managed by WhereIsThing. Do not edit manually."; } return "WhereIsThing 保存的本地预设内容,请勿手动编辑。"; case "ActiveLocalPresetId": if (!isChinese) { return "Preset ID currently selected for local use. Do not edit manually."; } return "当前本地玩家使用的预设 ID,请勿手动编辑。"; case "SelectedSharedPresetId": if (!isChinese) { return "Shared preset ID currently selected by this client. Do not edit manually."; } return "当前客户端选择的共享预设 ID,请勿手动编辑。"; case "ShareMode": if (!isChinese) { return "Whether the host shares built-in presets or published presets with clients."; } return "房主是否向客机共享默认预设或已发布预设。"; default: return string.Empty; } } private static ConfigEntryBase TryGetConfigEntry(object instance) { if (instance == null) { return null; } Type type = instance.GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (typeof(ConfigEntryBase).IsAssignableFrom(fieldInfo.FieldType)) { object? value = fieldInfo.GetValue(instance); return (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (typeof(ConfigEntryBase).IsAssignableFrom(propertyInfo.PropertyType) && propertyInfo.GetIndexParameters().Length == 0) { try { object? value2 = propertyInfo.GetValue(instance, null); return (ConfigEntryBase)((value2 is ConfigEntryBase) ? value2 : null); } catch { return null; } } } return null; } private static bool IsWhereIsThingEntry(ConfigEntryBase entry) { try { string text = ((entry == null || entry.ConfigFile == null) ? null : entry.ConfigFile.ConfigFilePath); return !string.IsNullOrEmpty(text) && text.EndsWith("com.wuyachiyu.WhereIsThing.cfg", StringComparison.OrdinalIgnoreCase); } catch { return false; } } private static void SetDescription(ConfigEntryBase entry, string text) { if (entry != null && entry.Description != null && !(DescriptionBackingField == null) && !string.IsNullOrEmpty(text)) { DescriptionBackingField.SetValue(entry.Description, text); } } } internal static class ThingUi { public static bool IsChinese { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((int)LocalizedText.CURRENT_LANGUAGE != 9) { return (int)LocalizedText.CURRENT_LANGUAGE == 10; } return true; } } public static string Text(string english, string chinese) { if (!IsChinese) { return english; } return chinese; } public static string PresetWindowTitle(bool allowEditing) { if (!allowEditing) { return Text("Shared Presets", "共享预设"); } return Text("WhereIsThing Presets", "WhereIsThing 预设"); } public static string PresetWindowSubtitle(bool allowEditing, bool usingFallbackPresets) { if (allowEditing) { return Text("Manage preset contents and sharing.", "管理预设内容与共享。"); } if (usingFallbackPresets) { return Text("Host is not sharing presets. Using fallback presets.", "房主未共享预设,当前使用保底预设。"); } return Text("Choose one preset for your own scan settings.", "为你自己的扫描设置选择一个预设。"); } public static string SelectionWindowTitle() { return Text("Preset Targets", "预设目标"); } public static string SelectionWindowSubtitle() { return Text("Choose which items and targets belong to this preset.", "选择哪些物品和目标属于这个预设。"); } public static string SearchPlaceholder() { return Text("Search", "搜索"); } public static string SelectedOnly() { return Text("Selected only", "仅显示已选"); } public static string SelectVisible() { return Text("Select visible", "全选当前"); } public static string ClearVisible() { return Text("Clear visible", "清除当前"); } public static string Cancel() { return Text("Cancel", "取消"); } public static string Apply() { return Text("Apply", "应用"); } public static string Close() { return Text("Close", "关闭"); } public static string LanguageLabel(ThingNameLanguage language) { return Text("Language: ", "语言:") + GetLanguageDisplay(language); } public static string CategoryLabel(string category, ThingNameLanguage language) { return Text("Category: ", "分类:") + ThingCatalog.GetCategoryDisplay(category, language); } public static string SelectedCount(int selectedCount, int totalCount) { if (!IsChinese) { return string.Format(CultureInfo.InvariantCulture, "{0} selected / {1}", selectedCount, totalCount); } return string.Format(CultureInfo.InvariantCulture, "已选 {0} / {1}", selectedCount, totalCount); } public static string NoMatchingTargets() { return Text("No matching targets", "没有匹配目标"); } public static string ShareModeLabel(ThingPresetShareMode shareMode) { return shareMode switch { ThingPresetShareMode.BuiltInOnly => Text("Share: Built-in only", "共享:仅默认预设"), ThingPresetShareMode.PublishedPresets => Text("Share: Published presets", "共享:已发布预设"), _ => Text("Share: Off", "共享:关闭"), }; } public static string NewPreset() { return Text("New preset", "新增预设"); } public static string Edit() { return Text("Edit", "编辑"); } public static string Rename() { return Text("Rename", "重命名"); } public static string RenamePresetTitle() { return Text("Rename custom preset", "重命名自定义预设"); } public static string PresetNamePlaceholder() { return Text("Preset name", "预设名称"); } public static string Save() { return Text("Save", "保存"); } public static string PresetNameRequired() { return Text("Enter a preset name.", "请输入预设名称。"); } public static string Hide() { return Text("Hide", "隐藏"); } public static string Publish() { return Text("Publish", "公开"); } public static string Delete() { return Text("Delete", "删除"); } public static string Use(bool active) { if (!active) { return Text("Use", "使用"); } return Text("Using", "使用中"); } public static string LocalScanSettings() { return Text("Your scan settings", "你的扫描设置"); } public static string ScanModeLabel(ThingScanMode scanMode, float durationSeconds) { if (scanMode == ThingScanMode.Persistent) { return Text("Mode: Persistent", "模式:常驻"); } if (!IsChinese) { return string.Format(CultureInfo.InvariantCulture, "Mode: Timed {0:0}s", durationSeconds); } return string.Format(CultureInfo.InvariantCulture, "模式:定时 {0:0}s", durationSeconds); } public static string ScopeTitle() { return Text("Locations", "显示范围"); } public static string Ground() { return Text("Ground", "地面"); } public static string Held() { return Text("Held", "手持"); } public static string Backpack() { return Text("Backpack", "背包"); } public static string Luggage() { return Text("Luggage", "行李箱"); } public static string Statue() { return Text("Statue", "雕像"); } public static string TimeMinus() { return "-"; } public static string TimePlus() { return "+"; } public static string EmptyPresets() { return Text("No presets", "暂无预设"); } public static string NoTargets() { return Text("No targets", "暂无目标"); } public static string PublishedTag() { return Text("Published", "已公开"); } public static string BuiltInTag() { return Text("Built-in", "保底"); } public static string CustomPresetName(int index) { if (!IsChinese) { return "Custom Preset " + index; } return "自定义预设 " + index; } public static string MigratedPresetName() { return Text("Migrated", "旧配置导入"); } public static string AchievementPresetName() { return Text("Achievement", "成就探索"); } public static string SurvivalPresetName() { return Text("Survival Medical", "生存急救"); } public static string AscentEightPresetName() { return Text("Ascent 8", "天阶 8"); } public static string GetLanguageDisplay(ThingNameLanguage language) { return language switch { ThingNameLanguage.English => "English", ThingNameLanguage.SimplifiedChinese => "简体中文", _ => Text("Follow Game", "跟随游戏"), }; } } internal sealed class ThingLabel { private readonly string _key; private readonly Transform _target; private readonly Func _positionProvider; private readonly Func _isValid; private readonly Func _titleProvider; private readonly GameObject _root; private readonly CanvasGroup _group; private readonly List _shadowTexts = new List(); private readonly TextMeshProUGUI _mainText; private readonly TextMeshProUGUI _arrow; private float _fontSize; private static readonly Vector2[] ShadowOffsets = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 1f), new Vector2(0f, -1f), new Vector2(-1f, 0f), new Vector2(1f, 0f) }; public string Key => _key; public bool IsValid { get { if ((Object)(object)_target != (Object)null && _isValid != null) { return _isValid(); } return false; } } public ThingLabel(string key, Transform canvas, Transform target, Func titleProvider, Func isValid, TMP_FontAsset font, float fontSize) : this(key, canvas, target, titleProvider, isValid, null, font, fontSize) { } public ThingLabel(string key, Transform canvas, Transform target, Func titleProvider, Func isValid, Func positionProvider, TMP_FontAsset font, float fontSize) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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) //IL_0149: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) _key = key; _target = target; _positionProvider = positionProvider; _titleProvider = titleProvider; _isValid = isValid; _fontSize = fontSize; _root = new GameObject("WhereIsThingLabel"); _root.transform.SetParent(canvas, false); _root.layer = 5; _group = _root.AddComponent(); _group.blocksRaycasts = false; _group.interactable = false; for (int i = 0; i < ShadowOffsets.Length; i++) { TextMeshProUGUI val = CreateText("Shadow_" + i, font, fontSize); ((Graphic)val).color = new Color(0f, 0f, 0f, 0.9f); ((TMP_Text)val).rectTransform.anchoredPosition = ShadowOffsets[i]; _shadowTexts.Add(val); } _mainText = CreateText("MainText", font, fontSize); ((Graphic)_mainText).color = new Color(0.875f, 0.855f, 0.761f, 1f); GameObject val2 = new GameObject("OffscreenDirection"); val2.transform.SetParent(_root.transform, false); val2.layer = 5; _arrow = val2.AddComponent(); ((TMP_Text)_arrow).font = font; ((TMP_Text)_arrow).text = "^"; ((TMP_Text)_arrow).alignment = (TextAlignmentOptions)514; ((TMP_Text)_arrow).fontSize = 22f; ((Graphic)_arrow).color = new Color(1f, 0.85f, 0.2f, 1f); ((Graphic)_arrow).raycastTarget = false; ((TMP_Text)_arrow).rectTransform.sizeDelta = new Vector2(18f, 18f); ((TMP_Text)_arrow).rectTransform.anchoredPosition = new Vector2(0f, -28f); ((Behaviour)_arrow).enabled = false; } public void ApplyStyle(TMP_FontAsset font, float fontSize) { if ((Object)(object)font == (Object)null) { return; } _fontSize = Mathf.Clamp(fontSize, 10f, 64f); ((TMP_Text)_mainText).font = font; ((TMP_Text)_mainText).fontSize = _fontSize; foreach (TextMeshProUGUI shadowText in _shadowTexts) { ((TMP_Text)shadowText).font = font; ((TMP_Text)shadowText).fontSize = _fontSize; } ((TMP_Text)_arrow).font = font; } public void Update(Camera camera, float maxDistance, bool showOffscreen) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null) { SetVisible(visible: false); return; } Vector3 val = ((_positionProvider == null) ? _target.position : _positionProvider()); Vector3 val2 = val + Vector3.up * 0.8f; Vector3 val3 = camera.WorldToViewportPoint(val2); float num = Vector3.Distance(((Component)camera).transform.position, val); bool flag = maxDistance <= 0f || num <= maxDistance; bool flag2 = val3.z > 0f; if (flag2 && val3.x >= 0f && val3.x <= 1f && val3.y >= 0f && val3.y <= 1f && flag) { _root.transform.position = camera.WorldToScreenPoint(val2); string arg = _titleProvider(); SetText($"{arg}\n{num:F0}m"); ((Behaviour)_arrow).enabled = false; SetVisible(visible: true); return; } if (!showOffscreen || !flag) { SetVisible(visible: false); return; } Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(val3.x - 0.5f, val3.y - 0.5f); if (!flag2) { val4 = -val4; } if (((Vector2)(ref val4)).sqrMagnitude < 0.001f) { val4 = Vector2.up; } ((Vector2)(ref val4)).Normalize(); Vector2 val5 = default(Vector2); ((Vector2)(ref val5))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f); float num2 = (float)Mathf.Min(Screen.width, Screen.height) * 0.42f; _root.transform.position = Vector2.op_Implicit(val5 + val4 * num2); SetText($"{num:F0}m"); ((Behaviour)_arrow).enabled = true; ((Transform)((TMP_Text)_arrow).rectTransform).localRotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(val4.y, val4.x) * 57.29578f - 90f); SetVisible(visible: true); } public void Dispose() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private TextMeshProUGUI CreateText(string name, TMP_FontAsset font, float size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(_root.transform, false); val.layer = 5; TextMeshProUGUI obj = val.AddComponent(); ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; ((TMP_Text)obj).richText = true; ((TMP_Text)obj).font = font; ((TMP_Text)obj).fontStyle = (FontStyles)0; ((TMP_Text)obj).fontSize = Mathf.Clamp(size, 10f, 64f); ((TMP_Text)obj).rectTransform.sizeDelta = new Vector2(320f, 96f); ((TMP_Text)obj).rectTransform.anchoredPosition = Vector2.zero; return obj; } private void SetVisible(bool visible) { _group.alpha = (visible ? 1f : 0f); } private void SetText(string value) { ((TMP_Text)_mainText).text = value; foreach (TextMeshProUGUI shadowText in _shadowTexts) { ((TMP_Text)shadowText).text = value; } } } internal sealed class ThingPresetPickerWindow { private readonly Canvas _canvas; private readonly TMP_FontAsset _font; private readonly GameObject _root; private readonly GameObject _cursorWindowObject; private readonly MenuWindow _cursorWindow; private readonly RectTransform _panelRect; private readonly RectTransform _content; private readonly TextMeshProUGUI _titleText; private readonly TextMeshProUGUI _subtitleText; private readonly TextMeshProUGUI _shareModeText; private readonly Button _shareModeButton; private readonly Button _newButton; private readonly TextMeshProUGUI _settingsTitleText; private readonly TextMeshProUGUI _scanModeText; private readonly TextMeshProUGUI _durationText; private readonly Button _durationMinusButton; private readonly Button _durationPlusButton; private readonly Dictionary _scopeToggles = new Dictionary(); private readonly List _presets = new List(); private GameObject _renameOverlay; private TMP_InputField _renameInput; private TextMeshProUGUI _renameTitleText; private TextMeshProUGUI _renameErrorText; private Func _summaryProvider; private Action _usePreset; private Action _editPreset; private Action _renamePreset; private Action _togglePublished; private Action _deletePreset; private Action _createPreset; private Action _setShareMode; private Action _setScope; private Action _cycleScanMode; private Action _adjustDisplayDuration; private bool _usingFallbackPresets; private bool _allowEditing; private bool _isOpen; private bool _isRebuilding; private bool _previousCursorVisible; private CursorLockMode _previousCursorLockState; private ThingPresetShareMode _shareMode; private ThingLocationScope _scopes; private ThingScanMode _scanMode; private float _displayDuration; private string _activePresetId; private string _renamingPresetId; public bool IsOpen => _isOpen; public ThingPresetPickerWindow(Canvas canvas, TMP_FontAsset font) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Expected O, but got Unknown //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Expected O, but got Unknown //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_059b: Unknown result type (might be due to invalid IL or missing references) //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_060c: Expected O, but got Unknown //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_063c: Unknown result type (might be due to invalid IL or missing references) //IL_0648: Unknown result type (might be due to invalid IL or missing references) //IL_0653: Expected O, but got Unknown //IL_067e: Unknown result type (might be due to invalid IL or missing references) //IL_068d: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06ba: Unknown result type (might be due to invalid IL or missing references) //IL_06e7: Unknown result type (might be due to invalid IL or missing references) //IL_06f6: Unknown result type (might be due to invalid IL or missing references) //IL_0702: Unknown result type (might be due to invalid IL or missing references) //IL_070d: Expected O, but got Unknown //IL_0737: Unknown result type (might be due to invalid IL or missing references) //IL_0746: Unknown result type (might be due to invalid IL or missing references) //IL_0755: Unknown result type (might be due to invalid IL or missing references) //IL_0764: Unknown result type (might be due to invalid IL or missing references) //IL_0773: Unknown result type (might be due to invalid IL or missing references) _canvas = canvas; _font = font; _root = CreateRect("WhereIsThingPresetPickerOverlay", ((Component)canvas).transform); Stretch(_root.GetComponent(), 0f, 0f, 0f, 0f); Image obj = _root.AddComponent(); ((Graphic)obj).color = new Color(0f, 0f, 0f, 0.54f); ((Graphic)obj).raycastTarget = true; _cursorWindowObject = CreateRect("WhereIsThingPresetMenuWindow", _root.transform); _cursorWindowObject.SetActive(false); _cursorWindow = _cursorWindowObject.AddComponent(); GameObject val = CreateRect("PresetPickerPanel", _root.transform); _panelRect = val.GetComponent(); _panelRect.anchorMin = new Vector2(0.2f, 0.14f); _panelRect.anchorMax = new Vector2(0.8f, 0.86f); _panelRect.offsetMin = Vector2.zero; _panelRect.offsetMax = Vector2.zero; ((Graphic)val.AddComponent()).color = new Color(0.075f, 0.08f, 0.075f, 0.98f); Outline obj2 = val.AddComponent(); ((Shadow)obj2).effectColor = new Color(0.7f, 0.66f, 0.52f, 0.75f); ((Shadow)obj2).effectDistance = new Vector2(2f, 2f); _titleText = CreateText(val.transform, "Title", string.Empty, 22f, (TextAlignmentOptions)513, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(22f, -42f), new Vector2(-22f, -8f), wrap: false, autoSize: true); _subtitleText = CreateText(val.transform, "Subtitle", string.Empty, 12f, (TextAlignmentOptions)513, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(22f, -72f), new Vector2(-22f, -40f), wrap: true, autoSize: true); _shareModeText = CreateButton(val.transform, "ShareMode", new Vector2(22f, -88f), new Vector2(232f, 38f), string.Empty, new UnityAction(CycleShareModeInternal)); _shareModeButton = ((Component)_shareModeText).GetComponentInParent