using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FraileyPortalSelector")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.7.0")] [assembly: AssemblyInformationalVersion("0.4.7+d00154020f09ce26374950d6b5ed9ba8f39b3265")] [assembly: AssemblyProduct("BetterPortals")] [assembly: AssemblyTitle("FraileyPortalSelector")] [assembly: AssemblyVersion("0.4.7.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 FraileyPortalSelector { [BepInPlugin("com.fraileywoodworks.portalselector", "BetterPortals", "0.4.7")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.fraileywoodworks.portalselector"; public const string Name = "BetterPortals"; public const string Version = "0.4.7"; internal const int MaxNameLength = 32; internal static Plugin Instance; internal static readonly Harmony Harmony = new Harmony("com.fraileywoodworks.portalselector"); private void Awake() { Instance = this; Harmony.PatchAll(); if (!Application.isBatchMode) { PortalVisualSettings.Bind(((BaseUnityPlugin)this).Config); ((Component)this).gameObject.AddComponent(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded; portal names capped at {2} characters", "BetterPortals", "0.4.7", 32)); } private void OnDestroy() { Harmony.UnpatchSelf(); } internal static void LogDebug(string message) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogDebug((object)message); } } } internal static class PortalVisualSettings { internal const float DefaultTitleFontSize = 40f; internal const float DefaultEntryFontSize = 31f; internal const float DefaultHintFontSize = 17f; internal const float DefaultBiomeFontSize = 9.3f; internal const float DefaultHomeIconSize = 13.2f; internal const float DefaultOutlineWidth = 0f; internal const float DefaultHoverScale = 1.1f; internal const float DefaultHoverExpandSeconds = 0.08f; internal const float DefaultHoverContractSeconds = 0.1f; internal const float DefaultPanelWidth = 620f; internal const float DefaultPanelYOffset = 0f; internal const float DefaultRowHeight = 46f; internal const float DefaultRowSpacing = 2f; internal const float DefaultMaxListHeight = 414f; internal const float DefaultBackdropOpacity = 1f; internal const float DefaultFadeInSeconds = 0.06f; internal const float DefaultFadeOutSeconds = 0.05f; internal const float DefaultTriggerMultiplier = 1.5625f; internal const float DefaultRowKnotGap = 18f; private const string DefaultTitleColor = "#FF8F00FF"; private const string DefaultEntryColor = "#FFFFFFFF"; private const string DefaultHintColor = "#B8B8B3FF"; private const string DefaultBiomeColor = "#FFFFFFFF"; private const string DefaultOutlineColor = "#000000D9"; private const string DefaultOrnamentColor = "#FF8F00FF"; private static ConfigEntry titleFontSize; private static ConfigEntry entryFontSize; private static ConfigEntry hintFontSize; private static ConfigEntry biomeFontSize; private static ConfigEntry homeIconSize; private static ConfigEntry titleColor; private static ConfigEntry entryColor; private static ConfigEntry hintColor; private static ConfigEntry biomeColor; private static ConfigEntry outlineColor; private static ConfigEntry outlineWidth; private static ConfigEntry hoverScale; private static ConfigEntry hoverExpandSeconds; private static ConfigEntry hoverContractSeconds; private static ConfigEntry panelWidth; private static ConfigEntry panelYOffset; private static ConfigEntry rowHeight; private static ConfigEntry rowSpacing; private static ConfigEntry maxListHeight; private static ConfigEntry backdropOpacity; private static ConfigEntry ornamentColor; private static ConfigEntry showMenuOrnament; private static ConfigEntry showRowKnots; private static ConfigEntry rowKnotGap; private static ConfigEntry fadeInSeconds; private static ConfigEntry fadeOutSeconds; private static ConfigEntry triggerMultiplier; private static ConfigEntry showBiomeSubtitle; private static ConfigEntry preferHomeOnOpen; private static ConfigEntry showControlHints; private static ConfigEntry setHomeKeyboardShortcut; internal static float TitleFontSize => Clamp(titleFontSize, 40f, 12f, 96f); internal static float EntryFontSize => Clamp(entryFontSize, 31f, 12f, 72f); internal static float HintFontSize => Clamp(hintFontSize, 17f, 8f, 48f); internal static float BiomeFontSize => Clamp(biomeFontSize, 9.3f, 8f, 48f); internal static float HomeIconSize => Clamp(homeIconSize, 13.2f, 12f, 36f); internal static Color TitleColor => ParseColor(titleColor, "#FF8F00FF"); internal static Color EntryColor => ParseColor(entryColor, "#FFFFFFFF"); internal static Color HintColor => ParseColor(hintColor, "#B8B8B3FF"); internal static Color BiomeColor => ParseColor(biomeColor, "#FFFFFFFF"); internal static Color OutlineColor => ParseColor(outlineColor, "#000000D9"); internal static float OutlineWidth => Clamp(outlineWidth, 0f, 0f, 1f); internal static float HoverScale => Clamp(hoverScale, 1.1f, 1f, 1.5f); internal static float HoverExpandSeconds => Clamp(hoverExpandSeconds, 0.08f, 0.01f, 1f); internal static float HoverContractSeconds => Clamp(hoverContractSeconds, 0.1f, 0.01f, 1f); internal static float PanelWidth => Clamp(panelWidth, 620f, 320f, 1400f); internal static float PanelYOffset => Clamp(panelYOffset, 0f, -500f, 500f); internal static float RowHeight => Clamp(rowHeight, 46f, 28f, 96f); internal static float RowSpacing => Clamp(rowSpacing, 2f, 0f, 24f); internal static float MaxListHeight => Clamp(maxListHeight, 414f, 80f, 900f); internal static float BackdropOpacity => Clamp(backdropOpacity, 1f, 0f, 1f); internal static Color OrnamentColor => ParseColor(ornamentColor, "#FF8F00FF"); internal static bool ShowMenuOrnament => showMenuOrnament?.Value ?? true; internal static bool ShowRowKnots => showRowKnots?.Value ?? true; internal static float RowKnotGap => Clamp(rowKnotGap, 18f, 0f, 100f); internal static float FadeInSeconds => Clamp(fadeInSeconds, 0.06f, 0.01f, 1f); internal static float FadeOutSeconds => Clamp(fadeOutSeconds, 0.05f, 0.01f, 1f); internal static float TriggerMultiplier => Clamp(triggerMultiplier, 1.5625f, 1f, 2f); internal static bool ShowBiomeSubtitle => showBiomeSubtitle?.Value ?? true; internal static bool PreferHomeOnOpen => preferHomeOnOpen?.Value ?? true; internal static bool ShowControlHints => showControlHints?.Value ?? true; internal static KeyboardShortcut SetHomeKeyboardShortcut => (KeyboardShortcut)(((??)setHomeKeyboardShortcut?.Value) ?? new KeyboardShortcut((KeyCode)104, Array.Empty())); internal static void Bind(ConfigFile config) { //IL_045e: Unknown result type (might be due to invalid IL or missing references) titleFontSize = BindRange(config, "Visual - Typography", "Title Font Size", 40f, 12f, 96f, "Portal selector heading size."); entryFontSize = BindRange(config, "Visual - Typography", "Entry Font Size", 31f, 12f, 72f, "Destination row text size."); hintFontSize = BindRange(config, "Visual - Typography", "Hint Font Size", 17f, 8f, 48f, "Size of the close-instruction text below the heading."); biomeFontSize = BindRange(config, "Visual - Typography", "Biome Font Size", 9.3f, 8f, 48f, "Size of the optional biome subtitle beneath each portal name."); homeIconSize = BindRange(config, "Visual - Typography", "Home Icon Size", 13.2f, 12f, 36f, "Size of Valheim's native favorite-star icon beside the selected Home portal."); titleColor = BindColor(config, "Visual - Typography", "Title Color", "#FF8F00FF", "Heading color as #RRGGBB or #RRGGBBAA."); entryColor = BindColor(config, "Visual - Typography", "Entry Color", "#FFFFFFFF", "Destination text color as #RRGGBB or #RRGGBBAA."); hintColor = BindColor(config, "Visual - Typography", "Hint Color", "#B8B8B3FF", "Instruction text color as #RRGGBB or #RRGGBBAA."); biomeColor = BindColor(config, "Visual - Typography", "Biome Color", "#FFFFFFFF", "Biome subtitle color as #RRGGBB or #RRGGBBAA."); outlineColor = BindColor(config, "Visual - Typography", "Font Outline Color", "#000000D9", "Text outline color as #RRGGBB or #RRGGBBAA."); outlineWidth = BindRange(config, "Visual - Typography", "Font Outline Width", 0f, 0f, 1f, "TextMesh Pro outline width for all selector text."); hoverScale = BindRange(config, "Visual - Hover", "Hover Scale", 1.1f, 1f, 1.5f, "Scale of the selected or hovered destination label."); hoverExpandSeconds = BindRange(config, "Visual - Hover", "Hover Expand Duration", 0.08f, 0.01f, 1f, "Seconds used for the eased hover expansion."); hoverContractSeconds = BindRange(config, "Visual - Hover", "Hover Contract Duration", 0.1f, 0.01f, 1f, "Seconds used for the eased hover contraction."); panelWidth = BindRange(config, "Visual - Layout", "Panel Width", 620f, 320f, 1400f, "Width of the centered portal selector in native UI units."); panelYOffset = BindRange(config, "Visual - Layout", "Panel Y Offset", 0f, -500f, 500f, "Vertical offset from screen center in native UI units."); rowHeight = BindRange(config, "Visual - Layout", "Row Height", 46f, 28f, 96f, "Height of each destination row."); rowSpacing = BindRange(config, "Visual - Layout", "Row Spacing", 2f, 0f, 24f, "Vertical spacing between destination rows."); maxListHeight = BindRange(config, "Visual - Layout", "Maximum List Height", 414f, 80f, 900f, "Maximum visible destination-list height before scrolling."); backdropOpacity = BindRange(config, "Visual - Layout", "Dark Backdrop Opacity", 1f, 0f, 1f, "Opacity multiplier for Valheim's native dark backdrop; 1 preserves the v20 appearance."); ornamentColor = BindColor(config, "Visual - Ornaments", "Ornament and Knot Color", "#FF8F00FF", "Menu ornament and row-knot color as #RRGGBB or #RRGGBBAA."); showMenuOrnament = config.Bind("Visual - Ornaments", "Show Menu Ornament", true, "Show Valheim's native menu ornament behind the selector."); showRowKnots = config.Bind("Visual - Ornaments", "Show Row Knots", true, "Show the native knot marks beside a hovered or controller-selected destination."); rowKnotGap = BindRange(config, "Visual - Ornaments", "Row Knot Gap", 18f, 0f, 100f, "Horizontal gap between the rendered destination label and each native knot mark."); fadeInSeconds = BindRange(config, "Visual - Animation", "Fade In Duration", 0.06f, 0.01f, 1f, "Seconds used for the selector fade-in."); fadeOutSeconds = BindRange(config, "Visual - Animation", "Fade Out Duration", 0.05f, 0.01f, 1f, "Seconds used for the selector fade-out."); triggerMultiplier = BindRange(config, "Portal Interaction", "Portal Trigger Multiplier", 1.5625f, 1f, 2f, "Client-local trigger and open-menu range multiplier. The server enforces a fixed 9.375-metre safety limit."); showBiomeSubtitle = config.Bind("Portal List", "Show Biome Subtitle", true, "Show the portal's biome in smaller white text beneath its name."); preferHomeOnOpen = config.Bind("Portal List", "Prefer Home On Open", true, "Select and scroll to the Home portal when the list opens."); showControlHints = config.Bind("Portal List", "Show Control Hints", true, "Show short keyboard or controller instructions above the destination list."); setHomeKeyboardShortcut = config.Bind("Portal List", "Set Home Keyboard Shortcut", new KeyboardShortcut((KeyCode)104, Array.Empty()), "Keyboard shortcut that sets or clears Home on the selected destination."); MigrateLegacyVisualDefaults(config); Watch(titleFontSize); Watch(entryFontSize); Watch(hintFontSize); Watch(biomeFontSize); Watch(homeIconSize); Watch(titleColor); Watch(entryColor); Watch(hintColor); Watch(biomeColor); Watch(outlineColor); Watch(outlineWidth); Watch(hoverScale); Watch(hoverExpandSeconds); Watch(hoverContractSeconds); Watch(panelWidth); Watch(panelYOffset); Watch(rowHeight); Watch(rowSpacing); Watch(maxListHeight); Watch(backdropOpacity); Watch(ornamentColor); Watch(showMenuOrnament); Watch(showRowKnots); Watch(rowKnotGap); Watch(fadeInSeconds); Watch(fadeOutSeconds); Watch(triggerMultiplier); Watch(showBiomeSubtitle); Watch(preferHomeOnOpen); Watch(showControlHints); Watch(setHomeKeyboardShortcut); } private static void MigrateLegacyVisualDefaults(ConfigFile config) { bool flag = false; if (Mathf.Approximately(biomeFontSize.Value, 15.5f)) { biomeFontSize.Value = 9.3f; flag = true; } if (Mathf.Approximately(homeIconSize.Value, 22f)) { homeIconSize.Value = 13.2f; flag = true; } if (Mathf.Approximately(panelYOffset.Value, 120f)) { panelYOffset.Value = 0f; flag = true; } if (Mathf.Approximately(triggerMultiplier.Value, 1.25f)) { triggerMultiplier.Value = 1.5625f; flag = true; } if (string.Equals(entryColor.Value?.Trim(), "#DBDBDBFF", StringComparison.OrdinalIgnoreCase)) { entryColor.Value = "#FFFFFFFF"; flag = true; } if (flag) { config.Save(); } } private static ConfigEntry BindRange(ConfigFile config, string section, string key, float value, float minimum, float maximum, string description) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return config.Bind(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(minimum, maximum), Array.Empty())); } private static ConfigEntry BindColor(ConfigFile config, string section, string key, string value, string description) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return config.Bind(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty())); } private static void Watch(ConfigEntry entry) { entry.SettingChanged += OnSettingChanged; } private static void OnSettingChanged(object sender, EventArgs args) { PortalController.Instance?.MarkVisualsDirty(); } private static float Clamp(ConfigEntry entry, float fallback, float minimum, float maximum) { return Mathf.Clamp(entry?.Value ?? fallback, minimum, maximum); } private static Color ParseColor(ConfigEntry entry, string fallback) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) string text = entry?.Value; if (!string.IsNullOrWhiteSpace(text)) { text = text.Trim(); if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } Color result = default(Color); if (ColorUtility.TryParseHtmlString(text, ref result)) { return result; } } Color result2 = default(Color); ColorUtility.TryParseHtmlString(fallback, ref result2); return result2; } } internal static class PortalNames { internal static string Sanitize(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } string text = new string(value.Where((char c) => c >= ' ' && c != '\u007f').Take(32).ToArray()); if (text.Length > 0 && char.IsHighSurrogate(text[text.Length - 1])) { text = text.Substring(0, text.Length - 1); } return text; } } internal static class PortalHome { private const string KeyPrefix = "com.fraileywoodworks.portalselector.home.v1."; private static string CurrentKey() { ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null)) { return "com.fraileywoodworks.portalselector.home.v1." + instance.GetWorldUID(); } return null; } internal static bool TryGet(out ZDOID id) { //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_0084: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) id = ZDOID.None; Player localPlayer = Player.m_localPlayer; string text = CurrentKey(); if (!Object.op_Implicit((Object)(object)localPlayer) || string.IsNullOrEmpty(text) || localPlayer.m_customData == null || !localPlayer.m_customData.TryGetValue(text, out var value)) { return false; } string[] array = value.Split(new char[1] { ':' }); if (array.Length != 2 || !long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !uint.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { return false; } id = new ZDOID(result, result2); return id != ZDOID.None; } internal static bool Set(ZDOID id) { //IL_001c: 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) Player localPlayer = Player.m_localPlayer; string text = CurrentKey(); if (!Object.op_Implicit((Object)(object)localPlayer) || string.IsNullOrEmpty(text) || id == ZDOID.None) { return false; } Player val = localPlayer; if (val.m_customData == null) { val.m_customData = new Dictionary(); } localPlayer.m_customData[text] = ((ZDOID)(ref id)).UserID.ToString(CultureInfo.InvariantCulture) + ":" + ((ZDOID)(ref id)).ID.ToString(CultureInfo.InvariantCulture); return true; } internal static bool Clear() { Player localPlayer = Player.m_localPlayer; string text = CurrentKey(); if (Object.op_Implicit((Object)(object)localPlayer) && !string.IsNullOrEmpty(text) && localPlayer.m_customData != null) { return localPlayer.m_customData.Remove(text); } return false; } } internal static class PortalBiomes { internal static Biome Normalize(int value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Biome val = (Biome)value; if (Rank(val) >= 9) { return (Biome)0; } return val; } internal static int Rank(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((int)biome <= 16) { switch (biome - 1) { default: if ((int)biome != 8) { if ((int)biome != 16) { break; } return 4; } return 1; case 0: return 0; case 1: return 2; case 3: return 3; case 2: break; } } else if ((int)biome <= 64) { if ((int)biome == 32) { return 6; } if ((int)biome == 64) { return 7; } } else { if ((int)biome == 256) { return 8; } if ((int)biome == 512) { return 5; } } return 9; } internal static string DisplayName(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((int)biome <= 16) { switch (biome - 1) { default: if ((int)biome != 8) { if ((int)biome != 16) { break; } return "Plains"; } return "Black Forest"; case 0: return "Meadows"; case 1: return "Swamp"; case 3: return "Mountains"; case 2: break; } } else if ((int)biome <= 64) { if ((int)biome == 32) { return "Ashlands"; } if ((int)biome == 64) { return "Deep North"; } } else { if ((int)biome == 256) { return "Ocean"; } if ((int)biome == 512) { return "Mistlands"; } } return "Other"; } } internal static class PortalOrderLedger { private static readonly Dictionary Orders = new Dictionary(); private static long loadedWorld; private static long nextOrder = 1L; private static bool initialized; private static bool loadingWorld; internal static void BeginWorldLoad() { loadingWorld = true; } internal static void EndWorldLoad(ZDOMan manager) { if (loadingWorld) { loadingWorld = false; if (manager != null) { Ensure(manager.GetPortalList()); } } } internal static void PrepareObservation() { if (!loadingWorld && !initialized && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ZDOMan instance = ZDOMan.instance; IEnumerable enumerable = ((instance != null) ? instance.GetPortalList() : null); Ensure(enumerable ?? Enumerable.Empty()); } } internal static void Ensure(IEnumerable portals) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } LoadCurrentWorld(); bool flag = false; foreach (ZDOID item in from id in (from z in portals where z != null && z.IsValid() select z.m_uid).Distinct() orderby (ulong)((ZDOID)(ref id)).UserID, ((ZDOID)(ref id)).ID select id) { if (!Orders.ContainsKey(item)) { Orders[item] = nextOrder++; flag = true; } } initialized = true; if (flag) { Save(); } } internal static long Get(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!Orders.TryGetValue(id, out var value)) { return long.MaxValue; } return value; } internal static void Observe(ZDO zdo) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!loadingWorld && initialized && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && zdo != null && zdo.IsValid()) { if (ZNet.instance.GetWorldUID() != loadedWorld) { initialized = false; } else if (!Orders.ContainsKey(zdo.m_uid)) { Orders[zdo.m_uid] = nextOrder++; Save(); } } } private static void LoadCurrentWorld() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) long worldUID = ZNet.instance.GetWorldUID(); if (initialized && loadedWorld == worldUID) { return; } loadedWorld = worldUID; nextOrder = 1L; initialized = false; Orders.Clear(); try { string path = CurrentPath(); if (!File.Exists(path)) { return; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { '\t' }); if (array2.Length == 3 && long.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && uint.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && long.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3) && result3 > 0) { Orders[new ZDOID(result, result2)] = result3; nextOrder = Math.Max(nextOrder, result3 + 1); } } } catch (Exception ex) { Plugin.LogDebug("Could not read portal creation-order ledger: " + ex.GetType().Name); } } private static string CurrentPath() { return Path.Combine(Paths.ConfigPath, $"BetterPortals.portal-order.{loadedWorld}.tsv"); } private static void Save() { string text = CurrentPath(); string text2 = text + ".tmp"; try { File.WriteAllLines(text2, Orders.OrderBy((KeyValuePair pair) => pair.Value).Select(delegate(KeyValuePair pair) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0036: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[5]; ZDOID key = pair.Key; array[0] = ((ZDOID)(ref key)).UserID.ToString(CultureInfo.InvariantCulture); array[1] = "\t"; key = pair.Key; array[2] = ((ZDOID)(ref key)).ID.ToString(CultureInfo.InvariantCulture); array[3] = "\t"; array[4] = pair.Value.ToString(CultureInfo.InvariantCulture); return string.Concat(array); })); if (File.Exists(text)) { try { File.Replace(text2, text, null); return; } catch (PlatformNotSupportedException) { File.Delete(text); File.Move(text2, text); return; } } File.Move(text2, text); } catch (Exception ex2) { Plugin.LogDebug("Could not save portal creation-order ledger: " + ex2.GetType().Name); } finally { try { if (File.Exists(text2)) { File.Delete(text2); } } catch { } } } } [HarmonyPatch(typeof(ZDOMan), "Load")] internal static class PortalOrderLoadPatch { private static void Prefix() { PortalOrderLedger.BeginWorldLoad(); } private static void Postfix(ZDOMan __instance) { PortalOrderLedger.EndWorldLoad(__instance); } private static Exception Finalizer(Exception __exception, ZDOMan __instance) { PortalOrderLedger.EndWorldLoad(__instance); return __exception; } } [HarmonyPatch(typeof(ZDOMan), "AddIfPortal")] internal static class PortalOrderObservationPatch { private static bool IsPortalPrefab(int prefabHash) { Game instance = Game.instance; if (Object.op_Implicit((Object)(object)instance) && instance.PortalPrefabHash != null) { return instance.PortalPrefabHash.Contains(prefabHash); } return false; } private static void Prefix(int __1, out bool __state) { __state = IsPortalPrefab(__1); if (__state) { PortalOrderLedger.PrepareObservation(); } } private static void Postfix(ZDO __0, bool __state) { if (__state) { PortalOrderLedger.Observe(__0); } } } internal static class PortalRanges { internal const float MaximumServerDistance = 9.375f; internal static float TriggerMultiplier => PortalVisualSettings.TriggerMultiplier; internal static float ClientDistance(TeleportWorld portal) { if (!Object.op_Implicit((Object)(object)portal) || !(portal.m_activationRange > 0f)) { return 9.375f; } return Mathf.Min(9.375f, portal.m_activationRange * TriggerMultiplier); } } [HarmonyPatch(typeof(TextInput), "RequestText")] internal static class PortalNameInputPatch { private static void Prefix(TextReceiver __0, ref int __2) { if (__0 is TeleportWorld) { __2 = 32; } } } [HarmonyPatch(typeof(TeleportWorld), "SetText")] internal static class PortalNameSendPatch { private static void Prefix(ref string __0) { __0 = PortalNames.Sanitize(__0); } } [HarmonyPatch(typeof(TeleportWorld), "RPC_SetTag")] internal static class PortalNameReceivePatch { private static void Prefix(ref string __1) { __1 = PortalNames.Sanitize(__1); } } [HarmonyPatch(typeof(TeleportWorld), "GetHoverText")] internal static class PortalHoverTextPatch { private static bool Prepare() { return !Application.isBatchMode; } private static void Postfix(ref string __result) { if (!string.IsNullOrEmpty(__result)) { int num = __result.IndexOf('\n'); string text = ((num >= 0) ? __result.Substring(0, num) : __result); int num2 = text.LastIndexOf(" [", StringComparison.Ordinal); if (num2 >= 0 && text.EndsWith("]", StringComparison.Ordinal)) { __result = text.Substring(0, num2) + ((num >= 0) ? __result.Substring(num) : string.Empty); } } } } [HarmonyPatch(typeof(Game), "Start")] internal static class RpcRegistrationPatch { private static void Postfix() { PortalRpc.Register(); } } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] internal static class PortalTravelPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix(TeleportWorld __instance, Player __0) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode || (Object)(object)__0 != (Object)(object)Player.m_localPlayer || PortalController.BypassOnce) { return true; } ZNetView component = ((Component)__instance).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || component.GetZDO() == null) { return true; } PortalController.Instance.Begin(__instance, component.GetZDO().m_uid); return false; } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class PortalCursorPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix() { if (Application.isBatchMode || !PortalController.CapturesInput) { return true; } if (!PortalController.WantsCursor) { return true; } PortalController.ApplySelectorCursor(center: false); return false; } } [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] internal static class PortalCrosshairPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix(Hud __instance) { if (Application.isBatchMode || !PortalController.CapturesInput) { return true; } if (Object.op_Implicit((Object)(object)__instance.m_crosshair)) { ((Component)__instance.m_crosshair).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)__instance.m_crosshairBow)) { ((Component)__instance.m_crosshairBow).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)__instance.m_hoverName)) { ((TMP_Text)__instance.m_hoverName).text = string.Empty; } return false; } } [HarmonyPatch(typeof(PlayerController), "InInventoryEtc")] internal static class PortalPlayerInputPatch { private static bool Prepare() { return !Application.isBatchMode; } private static void Postfix(ref bool __result) { if (!Application.isBatchMode && PortalController.CapturesInput) { __result = true; } } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class PortalCharacterInputPatch { private static bool Prepare() { return !Application.isBatchMode; } private static void Postfix(Player __instance, ref bool __result) { if (!Application.isBatchMode && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && PortalController.CapturesInput) { __result = false; } } } [HarmonyPatch(typeof(Menu), "Show")] internal static class PortalEscapeMenuPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix() { if (Application.isBatchMode || !PortalController.CapturesInput) { return true; } PortalController.Instance?.DismissFromMenuInput(); return false; } } [HarmonyPatch(typeof(Chat), "Update")] internal static class PortalChatInputPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix() { if (!Application.isBatchMode) { return !PortalController.CapturesInput; } return true; } } [HarmonyPatch(typeof(Chat), "InputText")] internal static class PortalChatOpenPatch { private static bool Prepare() { return !Application.isBatchMode; } private static bool Prefix() { if (!Application.isBatchMode) { return !PortalController.CapturesInput; } return true; } } [HarmonyPatch(typeof(TeleportWorldTrigger), "Awake")] internal static class PortalExitWatcherPatch { private static bool Prepare() { return !Application.isBatchMode; } private static void Postfix(TeleportWorldTrigger __instance) { if (!Application.isBatchMode) { (((Component)__instance).GetComponent() ?? ((Component)__instance).gameObject.AddComponent()).Initialize(((Component)__instance).GetComponentInParent(), __instance); } } } [HarmonyPatch(typeof(TeleportWorld), "UpdatePortal")] internal static class PortalGlowUpdateContextPatch { [ThreadStatic] private static TeleportWorld updating; private static bool Prepare() { return !Application.isBatchMode; } internal static bool IsUpdating(TeleportWorld portal) { return (Object)(object)updating == (Object)(object)portal; } private static void Prefix(TeleportWorld __instance) { if (!Application.isBatchMode) { updating = __instance; } } private static void Postfix() { updating = null; } private static Exception Finalizer(Exception __exception) { updating = null; return __exception; } } [HarmonyPatch(typeof(TeleportWorld), "TargetFound")] internal static class UnpairedPortalGlowPatch { private static bool Prepare() { return !Application.isBatchMode; } private static void Postfix(TeleportWorld __instance, ref bool __result) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (!(Application.isBatchMode | __result) && PortalGlowUpdateContextPatch.IsUpdating(__instance)) { Player localPlayer = Player.m_localPlayer; ZNetView component = ((Component)__instance).GetComponent(); if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)component) && component.IsValid() && component.GetZDO() != null && Object.op_Implicit((Object)(object)__instance.m_proximityRoot) && !string.IsNullOrWhiteSpace(component.GetZDO().GetString("tag", "")) && !(Vector3.Distance(((Component)localPlayer).transform.position, __instance.m_proximityRoot.position) > __instance.m_activationRange) && ((Humanoid)localPlayer).IsTeleportable(__instance.m_allowAllItems)) { __result = true; } } } } internal sealed class PortalExitWatcher : MonoBehaviour { private readonly HashSet localColliders = new HashSet(); private TeleportWorld portal; private BoxCollider[] boxes = Array.Empty(); private Vector3[] originalBoxSizes = Array.Empty(); private SphereCollider[] spheres = Array.Empty(); private float[] originalSphereRadii = Array.Empty(); private CapsuleCollider[] capsules = Array.Empty(); private float[] originalCapsuleRadii = Array.Empty(); private float[] originalCapsuleHeights = Array.Empty(); private float appliedMultiplier = -1f; private bool rangesCaptured; internal void Initialize(TeleportWorld sourcePortal, TeleportWorldTrigger trigger) { portal = sourcePortal; if (!rangesCaptured && Object.op_Implicit((Object)(object)trigger)) { boxes = ((Component)trigger).GetComponents(); originalBoxSizes = boxes.Select((BoxCollider box) => box.size).ToArray(); spheres = ((Component)trigger).GetComponents(); originalSphereRadii = spheres.Select((SphereCollider sphere) => sphere.radius).ToArray(); capsules = ((Component)trigger).GetComponents(); originalCapsuleRadii = capsules.Select((CapsuleCollider capsule) => capsule.radius).ToArray(); originalCapsuleHeights = capsules.Select((CapsuleCollider capsule) => capsule.height).ToArray(); rangesCaptured = true; } ApplyTriggerMultiplier(); } private void Update() { if (!Mathf.Approximately(appliedMultiplier, PortalRanges.TriggerMultiplier)) { ApplyTriggerMultiplier(); } } private void ApplyTriggerMultiplier() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!rangesCaptured) { return; } float triggerMultiplier = PortalRanges.TriggerMultiplier; for (int i = 0; i < boxes.Length; i++) { if (Object.op_Implicit((Object)(object)boxes[i])) { boxes[i].size = originalBoxSizes[i] * triggerMultiplier; } } for (int j = 0; j < spheres.Length; j++) { if (Object.op_Implicit((Object)(object)spheres[j])) { spheres[j].radius = originalSphereRadii[j] * triggerMultiplier; } } for (int k = 0; k < capsules.Length; k++) { if (Object.op_Implicit((Object)(object)capsules[k])) { capsules[k].radius = originalCapsuleRadii[k] * triggerMultiplier; capsules[k].height = originalCapsuleHeights[k] * triggerMultiplier; } } appliedMultiplier = triggerMultiplier; } private void OnTriggerEnter(Collider other) { localColliders.RemoveWhere((Collider collider) => !Object.op_Implicit((Object)(object)collider)); if (IsLocalPlayer(other)) { localColliders.Add(other); } } private void OnTriggerExit(Collider other) { if (IsLocalPlayer(other)) { localColliders.RemoveWhere((Collider collider) => !Object.op_Implicit((Object)(object)collider)); localColliders.Remove(other); if (localColliders.Count == 0) { PortalController.Instance?.CloseIfSource(portal); } } } private void OnDestroy() { localColliders.Clear(); PortalController.Instance?.CloseIfSource(portal); } private static bool IsLocalPlayer(Collider collider) { Player val = ((Component)collider).GetComponent() ?? ((Component)collider).GetComponentInParent(); if (Object.op_Implicit((Object)(object)val)) { return (Object)(object)val == (Object)(object)Player.m_localPlayer; } return false; } } internal static class PortalRpc { private readonly struct RequestWindow { internal readonly float Start; internal readonly int Count; internal RequestWindow(float start, int count) { Start = start; Count = count; } } private readonly struct ServerSession { internal readonly ZDOID Source; internal readonly long Nonce; internal readonly float Expires; internal readonly HashSet Destinations; internal ServerSession(ZDOID source, long nonce, float expires, IEnumerable destinations) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Source = source; Nonce = nonce; Expires = expires; Destinations = new HashSet(destinations); } } private const int ProtocolVersion = 2; private const string DirectoryRequest = "com.fraileywoodworks.portalselector.v2.directory.request"; private const string DirectoryResponse = "com.fraileywoodworks.portalselector.v2.directory.response"; private const string TravelRequest = "com.fraileywoodworks.portalselector.v2.travel.request"; private const string TravelResponse = "com.fraileywoodworks.portalselector.v2.travel.response"; private const float ServerSessionLifetime = 60f; private static readonly Dictionary Windows = new Dictionary(); private static readonly Dictionary Sessions = new Dictionary(); private static ZRoutedRpc registeredOn; internal static bool Register() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return false; } if (registeredOn == instance) { return true; } instance.Register("com.fraileywoodworks.portalselector.v2.directory.request", (Action)OnDirectoryRequest); instance.Register("com.fraileywoodworks.portalselector.v2.directory.response", (Action)OnDirectoryResponse); instance.Register("com.fraileywoodworks.portalselector.v2.travel.request", (Action)OnTravelRequest); instance.Register("com.fraileywoodworks.portalselector.v2.travel.response", (Action)OnTravelResponse); registeredOn = instance; return true; } internal static bool AskDirectory(ZDOID source, ZDOID savedHome, long nonce) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!Register() || !TryServerId(out var server)) { return false; } ZPackage val = new ZPackage(); val.Write(2); val.Write(source); val.Write(savedHome != ZDOID.None); if (savedHome != ZDOID.None) { val.Write(savedHome); } val.Write(nonce); ZRoutedRpc.instance.InvokeRoutedRPC(server, "com.fraileywoodworks.portalselector.v2.directory.request", new object[1] { val }); return true; } internal static bool AskTravel(ZDOID source, ZDOID destination, long nonce) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Register() || !TryServerId(out var server)) { return false; } ZPackage val = new ZPackage(); val.Write(2); val.Write(source); val.Write(destination); val.Write(nonce); ZRoutedRpc.instance.InvokeRoutedRPC(server, "com.fraileywoodworks.portalselector.v2.travel.request", new object[1] { val }); return true; } private static bool TryServerId(out long server) { server = 0L; if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (ZNet.instance.IsServer()) { server = ZNet.GetUID(); return true; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null) { return false; } server = serverPeer.m_uid; return true; } internal static bool TryPortal(ZDOID id, out ZDO portal) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; portal = ((instance == null) ? null : instance.GetPortalList()?.FirstOrDefault((Func)((ZDO z) => z != null && z.IsValid() && z.m_uid == id))); return portal != null; } private static bool NearSource(long sender, ZDO source) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || source == null) { return false; } if (instance.IsServer() && sender == ZNet.GetUID()) { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { return Vector3.Distance(((Component)localPlayer).transform.position, source.GetPosition()) <= 9.375f; } return false; } ZNetPeer peer = instance.GetPeer(sender); if (peer != null) { return Vector3.Distance(peer.m_refPos, source.GetPosition()) <= 9.375f; } return false; } private static bool RateAllowed(long sender) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (Windows.TryGetValue(sender, out var value) && realtimeSinceStartup - value.Start < 2f) { if (value.Count >= 4) { return false; } Windows[sender] = new RequestWindow(value.Start, value.Count + 1); } else { Windows[sender] = new RequestWindow(realtimeSinceStartup, 1); } return true; } private static void OnDirectoryRequest(long sender, ZPackage request) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Expected O, but got Unknown //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Expected I4, but got Unknown if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { if (request.ReadInt() != 2) { return; } ZDOID sourceId = request.ReadZDOID(); ZDOID savedHome = (request.ReadBool() ? request.ReadZDOID() : ZDOID.None); long num = request.ReadLong(); if (!RateAllowed(sender) || !TryPortal(sourceId, out var portal) || !NearSource(sender, portal)) { return; } WorldGenerator generator = WorldGenerator.instance; List list = (from z in ZDOMan.instance.GetPortalList() where z != null && z.IsValid() select z).ToList(); PortalOrderLedger.Ensure(list); List source = (from z in list where z.m_uid != sourceId select new PortalInfo(z.m_uid, PortalNames.Sanitize(z.GetString("tag", "")), (Biome)((generator != null) ? ((int)generator.GetBiome(z.GetPosition())) : 0), PortalOrderLedger.Get(z.m_uid)) into p where !string.IsNullOrWhiteSpace(p.Name) orderby PortalBiomes.Rank(p.Biome), p.CreationOrder select p).ThenBy(delegate(PortalInfo p) { //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) ZDOID id = p.Id; return (ulong)((ZDOID)(ref id)).UserID; }).ThenBy((PortalInfo p) => ((ZDOID)(ref p.Id)).ID).ToList(); bool flag = savedHome != ZDOID.None && list.Any((ZDO zdo) => zdo.m_uid == savedHome && !string.IsNullOrWhiteSpace(PortalNames.Sanitize(zdo.GetString("tag", "")))); List list2 = source.Take(512).ToList(); if (flag && savedHome != sourceId && !list2.Any((PortalInfo portalInfo) => portalInfo.Id == savedHome)) { list2[list2.Count - 1] = source.First((PortalInfo portalInfo) => portalInfo.Id == savedHome); list2 = (from p in list2 orderby PortalBiomes.Rank(p.Biome), p.CreationOrder select p).ThenBy(delegate(PortalInfo p) { //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) ZDOID id = p.Id; return (ulong)((ZDOID)(ref id)).UserID; }).ThenBy((PortalInfo p) => ((ZDOID)(ref p.Id)).ID).ToList(); } Sessions[sender] = new ServerSession(sourceId, num, Time.realtimeSinceStartup + 60f, list2.Select((PortalInfo portalInfo) => portalInfo.Id)); ZPackage val = new ZPackage(); val.Write(2); val.Write(num); val.Write(flag); val.Write(list2.Count); foreach (PortalInfo item in list2) { val.Write(item.Id); val.Write(item.Name); val.Write((int)item.Biome); val.Write(item.CreationOrder); } ZRoutedRpc.instance.InvokeRoutedRPC(sender, "com.fraileywoodworks.portalselector.v2.directory.response", new object[1] { val }); } catch (Exception ex) { Plugin.LogDebug("Rejected malformed portal directory request: " + ex.GetType().Name); } } private static void OnDirectoryResponse(long sender, ZPackage package) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (!TryServerId(out var server) || sender != server) { return; } try { if (package.ReadInt() != 2) { return; } long responseNonce = package.ReadLong(); bool homeValid = package.ReadBool(); int num = package.ReadInt(); if (num < 0 || num > 512) { throw new InvalidDataException("Portal directory count was outside the protocol bounds."); } List list = new List(num); for (int i = 0; i < num; i++) { ZDOID val = package.ReadZDOID(); string text = PortalNames.Sanitize(package.ReadString()); Biome biome = PortalBiomes.Normalize(package.ReadInt()); long num2 = package.ReadLong(); if (val == ZDOID.None || string.IsNullOrWhiteSpace(text) || num2 <= 0) { throw new InvalidDataException("Portal directory record was invalid."); } list.Add(new PortalInfo(val, text, biome, num2)); } PortalController.Instance?.Show(responseNonce, homeValid, list); } catch (Exception ex) { Plugin.LogDebug("Rejected malformed portal directory response: " + ex.GetType().Name); } } private static void OnTravelRequest(long sender, ZPackage request) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0036: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { if (request.ReadInt() == 2) { ZDOID val = request.ReadZDOID(); ZDOID val2 = request.ReadZDOID(); long num = request.ReadLong(); ServerSession value; bool flag = Sessions.TryGetValue(sender, out value) && value.Source == val && value.Nonce == num && value.Expires >= Time.realtimeSinceStartup && value.Destinations.Contains(val2); Sessions.Remove(sender); if (!RateAllowed(sender) || !flag || !TryPortal(val, out var portal) || !NearSource(sender, portal) || !TryPortal(val2, out var portal2) || val2 == val || string.IsNullOrWhiteSpace(PortalNames.Sanitize(portal2.GetString("tag", "")))) { SendTravelResponse(sender, num, approved: false, null); } else { SendTravelResponse(sender, num, approved: true, portal2); } } } catch (Exception ex) { Plugin.LogDebug("Rejected malformed portal travel request: " + ex.GetType().Name); } } private static void OnTravelResponse(long sender, ZPackage package) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!TryServerId(out var server) || sender != server) { return; } try { if (package.ReadInt() == 2) { long responseNonce = package.ReadLong(); bool flag = package.ReadBool(); PortalController.Instance?.Complete(responseNonce, flag, (Vector3)(flag ? package.ReadVector3() : default(Vector3)), (Quaternion)(flag ? package.ReadQuaternion() : default(Quaternion))); } } catch (Exception ex) { Plugin.LogDebug("Rejected malformed portal travel response: " + ex.GetType().Name); } } private static void SendTravelResponse(long sender, long nonce, bool approved, ZDO destination) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(2); val.Write(nonce); val.Write(approved); if (approved && destination != null) { val.Write(destination.GetPosition()); val.Write(destination.GetRotation()); } ZRoutedRpc.instance.InvokeRoutedRPC(sender, "com.fraileywoodworks.portalselector.v2.travel.response", new object[1] { val }); } } internal readonly struct PortalInfo { internal readonly ZDOID Id; internal readonly string Name; internal readonly Biome Biome; internal readonly long CreationOrder; internal PortalInfo(ZDOID id, string name, Biome biome, long creationOrder) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected I4, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Id = id; Name = name; Biome = PortalBiomes.Normalize((int)biome); CreationOrder = Math.Max(1L, creationOrder); } } internal sealed class PortalController : MonoBehaviour { private const float DirectoryTimeout = 5f; private const float SessionLifetime = 60f; private const float TravelTimeout = 3f; private const float FirstEntryRetryWindow = 6f; private const float FirstEntryRetryInterval = 0.1f; private const float DirectoryResponseRetryInterval = 0.75f; internal static PortalController Instance; internal static bool BypassOnce; private ZDOID source; private TeleportWorld sourcePortal; private long nonce; private float requestStarted; private float sessionDeadline; private float nextOpenAllowed; private float travelDeadline; private GameObject panel; private CanvasGroup canvasGroup; private Transform content; private LayoutElement scrollLayout; private ScrollRect destinationScroll; private Button firstSelectable; private Button homeSelectable; private bool? previousMouseInput; private Vector3 openingMousePosition; private bool mouseChoiceArmed; private int cursorCenterFrames; private float fadeTarget; private bool resetAfterFade; private bool travelPending; private bool directoryReady; private bool pendingTeleport; private Vector3 pendingPosition; private Quaternion pendingRotation; private TeleportWorld deferredPortal; private ZDOID deferredSource; private float deferredStarted; private float deferredDeadline; private float nextDeferredAttempt; private RectTransform panelRect; private VerticalLayoutGroup panelLayout; private VerticalLayoutGroup contentLayout; private TMP_Text titleText; private TMP_Text hintText; private GameObject darkBackdrop; private CanvasGroup darkBackdropGroup; private GameObject menuOrnament; private Graphic[] menuOrnamentGraphics = Array.Empty(); private float[] menuOrnamentBaseAlphas = Array.Empty(); private bool visualsDirty; private readonly List rows = new List(); private readonly List portalRows = new List(); private readonly List currentPortals = new List(); private static TMP_FontAsset nativeFont; private static Material nativeFontMaterial; private static Sprite nativeHomeSprite; private static int nativeHomeSpriteSearchFrame = -1; private static bool cursorWarpPrepared; private static PropertyInfo inputMouseCurrentProperty; private static MethodInfo inputMouseWarpMethod; internal static bool CapturesInput { get { if ((Object)(object)Instance != (Object)null) { if (!Object.op_Implicit((Object)(object)Instance.panel) || !Instance.panel.activeSelf) { return Instance.travelPending; } return true; } return false; } } internal static bool WantsCursor { get { if ((Object)(object)Instance != (Object)null && Object.op_Implicit((Object)(object)Instance.panel) && Instance.panel.activeSelf && Instance.fadeTarget > 0f) { return !Instance.travelPending; } return false; } } private void Awake() { Instance = this; visualsDirty = true; PrepareCursorWarp(); } internal void MarkVisualsDirty() { visualsDirty = true; } internal void Begin(TeleportWorld portal, ZDOID sourceId) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)portal) && !CapturesInput && nonce == 0L && !Object.op_Implicit((Object)(object)deferredPortal) && !(Time.realtimeSinceStartup < nextOpenAllowed) && !AnotherModalIsVisible() && PortalCandidateIsUsable(portal, sourceId)) { deferredPortal = portal; deferredSource = sourceId; deferredStarted = Time.realtimeSinceStartup; deferredDeadline = deferredStarted + 6f; nextDeferredAttempt = deferredStarted + 0.1f; if (!TryStartRequest(portal, sourceId)) { Plugin.LogDebug($"Portal entry deferred for up to {6f:0.0}s while the world portal registry and routed RPC finish initializing."); } else if (deferredSource != ZDOID.None && !directoryReady) { nextDeferredAttempt = Time.realtimeSinceStartup + 0.75f; Plugin.LogDebug("Portal directory request sent; waiting for server acceptance."); } } } private bool TryStartRequest(TeleportWorld portal, ZDOID sourceId) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (!PortalCandidateIsUsable(portal, sourceId) || !PortalRpc.Register() || !PortalRpc.TryPortal(sourceId, out var _)) { return false; } sourcePortal = portal; source = sourceId; if (!SourceIsUsable()) { sourcePortal = null; source = ZDOID.None; return false; } nonce = DateTime.UtcNow.Ticks; directoryReady = false; requestStarted = Time.realtimeSinceStartup; sessionDeadline = requestStarted + 60f - 2f; PortalHome.TryGet(out var id); if (!PortalRpc.AskDirectory(source, id, nonce)) { sourcePortal = null; source = ZDOID.None; nonce = 0L; requestStarted = 0f; sessionDeadline = 0f; return false; } return true; } private static bool PortalCandidateIsUsable(TeleportWorld portal, ZDOID sourceId) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)portal) || !Object.op_Implicit((Object)(object)localPlayer) || sourceId == ZDOID.None) { return false; } ZNetView component = ((Component)portal).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || component.GetZDO() == null || component.GetZDO().m_uid != sourceId) { return false; } Vector3 val = (Object.op_Implicit((Object)(object)portal.m_proximityRoot) ? portal.m_proximityRoot.position : component.GetZDO().GetPosition()); return Vector3.Distance(((Component)localPlayer).transform.position, val) <= PortalRanges.ClientDistance(portal); } private void AdvanceDeferredBegin() { //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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) if (deferredSource == ZDOID.None) { return; } if (!Object.op_Implicit((Object)(object)deferredPortal)) { ClearDeferredBegin(); return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= deferredDeadline) { Plugin.LogDebug($"Deferred portal entry timed out after {Mathf.Max(0f, realtimeSinceStartup - deferredStarted):0.00}s; leave and re-enter the portal to retry."); ResetSession(0f); } else if (realtimeSinceStartup < nextOpenAllowed || AnotherModalIsVisible() || !PortalCandidateIsUsable(deferredPortal, deferredSource)) { Plugin.LogDebug("Deferred portal entry canceled because the player left range, opened another interface, or entered the post-travel cooldown."); ResetSession(0f); } else { if (realtimeSinceStartup < nextDeferredAttempt) { return; } if (nonce == 0L) { nextDeferredAttempt = realtimeSinceStartup + 0.1f; if (TryStartRequest(deferredPortal, deferredSource)) { nextDeferredAttempt = realtimeSinceStartup + 0.75f; Plugin.LogDebug("Deferred portal directory request sent; waiting for server acceptance."); } } else if (!directoryReady) { nextDeferredAttempt = realtimeSinceStartup + 0.75f; PortalHome.TryGet(out var id); if (!PortalRpc.AskDirectory(source, id, nonce)) { nextDeferredAttempt = realtimeSinceStartup + 0.1f; } } } } private void ClearDeferredBegin() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) deferredPortal = null; deferredSource = ZDOID.None; deferredStarted = 0f; deferredDeadline = 0f; nextDeferredAttempt = 0f; } internal void Show(long responseNonce, bool homeValid, List portals) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0251: 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_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Expected O, but got Unknown //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) if (responseNonce != nonce || travelPending || directoryReady) { return; } if (!SourceIsUsable()) { ResetSession(0f); return; } directoryReady = true; if (deferredSource != ZDOID.None) { float num = Mathf.Max(0f, Time.realtimeSinceStartup - deferredStarted); Plugin.LogDebug($"Deferred portal entry started successfully after {num:0.00}s and server acceptance."); ClearDeferredBegin(); } EnsureUi(); foreach (GameObject row in rows) { Object.Destroy((Object)(object)row); } rows.Clear(); portalRows.Clear(); currentPortals.Clear(); firstSelectable = null; homeSelectable = null; currentPortals.AddRange((from p in portals orderby PortalBiomes.Rank(p.Biome), p.CreationOrder select p).ThenBy(delegate(PortalInfo p) { //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) ZDOID id = p.Id; return (ulong)((ZDOID)(ref id)).UserID; }).ThenBy((PortalInfo p) => ((ZDOID)(ref p.Id)).ID)); Dictionary dictionary = currentPortals.GroupBy((PortalInfo p) => p.Name, StringComparer.OrdinalIgnoreCase).ToDictionary, string, int>((IGrouping g) => g.Key, (IGrouping g) => g.Count(), StringComparer.OrdinalIgnoreCase); Dictionary dictionary2 = new Dictionary(StringComparer.OrdinalIgnoreCase); if (PortalHome.TryGet(out var home) && (!homeValid || (home != source && !currentPortals.Any((PortalInfo portal) => portal.Id == home)))) { PortalHome.Clear(); home = ZDOID.None; ShowStatus("Home portal unavailable — choose a new Home"); } foreach (PortalInfo currentPortal in currentPortals) { dictionary2.TryGetValue(currentPortal.Name, out var value); value = (dictionary2[currentPortal.Name] = value + 1); string label = ((dictionary[currentPortal.Name] > 1) ? $"{currentPortal.Name} ({value}/{dictionary[currentPortal.Name]})" : currentPortal.Name); PortalInfo destination = currentPortal; Button val = AddRow(label, PortalBiomes.DisplayName(currentPortal.Biome), currentPortal.Id, delegate { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ActivateDestination(destination.Id); }, delegate { ToggleHome(destination); }, currentPortal.Id == home); if (!Object.op_Implicit((Object)(object)firstSelectable)) { firstSelectable = val; } if (currentPortal.Id == home) { homeSelectable = val; } } if (currentPortals.Count == 0) { AddRow("No named destinations found", string.Empty, ZDOID.None, null, null, isHome: false); } ConfigureRowNavigation(); UpdateHintText(); ApplyVisualSettings(); canvasGroup.alpha = 0f; canvasGroup.interactable = true; canvasGroup.blocksRaycasts = true; fadeTarget = 1f; resetAfterFade = false; panel.SetActive(true); LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)panel.transform); previousMouseInput = null; mouseChoiceArmed = false; SynchronizeInputSelection(centerMouse: true); if (Object.op_Implicit((Object)(object)homeSelectable) && PortalVisualSettings.PreferHomeOnOpen) { ScrollIntoView(((Component)homeSelectable).gameObject); } } internal void Complete(long responseNonce, bool approved, Vector3 position, Quaternion rotation) { //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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (responseNonce != nonce) { return; } travelPending = false; if (!approved || (Object)(object)Player.m_localPlayer == (Object)null) { RequestClose(invalidateRequest: true); return; } pendingTeleport = true; pendingPosition = position; pendingRotation = rotation; BeginFadeOut(resetWhenHidden: false); if (!Object.op_Implicit((Object)(object)panel) || !panel.activeSelf) { PerformPendingTeleport(); } } internal void CloseIfSource(TeleportWorld portal) { if (Object.op_Implicit((Object)(object)portal) && (Object)(object)portal == (Object)(object)deferredPortal) { Plugin.LogDebug("Deferred portal entry canceled when the player left the source trigger."); ClearDeferredBegin(); } if (Object.op_Implicit((Object)(object)portal) && (Object)(object)portal == (Object)(object)sourcePortal && nonce != 0L) { RequestClose(invalidateRequest: true); } } internal void DismissFromMenuInput() { RequestClose(invalidateRequest: true); } private void Update() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_014f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)panel) && Object.op_Implicit((Object)(object)Menu.instance) && Object.op_Implicit((Object)(object)Menu.instance.m_continueButton)) { EnsureUi(); } AdvanceDeferredBegin(); if (visualsDirty) { ApplyVisualSettings(); } if (nonce != 0L && !SourceIsUsable()) { RequestClose(invalidateRequest: true); } if (Object.op_Implicit((Object)(object)panel) && panel.activeSelf) { SynchronizeInputSelection(); AdvanceCursorCentering(); ArmMouseChoiceAfterMovement(); KeyboardShortcut setHomeKeyboardShortcut = PortalVisualSettings.SetHomeKeyboardShortcut; if (((KeyboardShortcut)(ref setHomeKeyboardShortcut)).IsDown() || ZInput.GetButtonDown("JoyButtonX")) { ToggleSelectedHome(); } else if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271) || ZInput.GetButtonDown("JoyButtonA")) { ConfirmSelected(); } else if (Input.GetKeyDown((KeyCode)27) || ZInput.GetButtonDown("JoyButtonB") || AnotherModalIsVisible()) { RequestClose(invalidateRequest: true); } KeepControllerSelectionVisible(); AdvanceFade(); } if (nonce != 0L && Time.realtimeSinceStartup >= sessionDeadline) { RequestClose(invalidateRequest: true); } if (travelPending && Time.realtimeSinceStartup >= travelDeadline) { RequestClose(invalidateRequest: true); } if (nonce != 0L && deferredSource == ZDOID.None && !travelPending && (!Object.op_Implicit((Object)(object)panel) || !panel.activeSelf) && Time.realtimeSinceStartup - requestStarted >= 5f) { ResetSession(0f); } if (pendingTeleport && (!Object.op_Implicit((Object)(object)panel) || !panel.activeSelf)) { PerformPendingTeleport(); } } private void EnsureUi() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_013f: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Expected O, but got Unknown //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Expected O, but got Unknown //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Expected O, but got Unknown //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Expected O, but got Unknown //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Expected O, but got Unknown //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)panel)) { return; } GameObject val = new GameObject("BetterPortals Canvas", new Type[3] { typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); val.transform.SetParent(((Component)this).transform, false); Canvas component = val.GetComponent(); component.renderMode = (RenderMode)0; component.overrideSorting = true; RectTransform component2 = val.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.pivot = new Vector2(0.5f, 0.5f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = Vector2.zero; } Menu instance = Menu.instance; Canvas val2 = ((instance != null) ? ((Component)instance).GetComponentInParent() : null); component.sortingOrder = (Object.op_Implicit((Object)(object)val2) ? (val2.sortingOrder + 1) : 1701); ConfigureScaler(val.GetComponent()); panel = new GameObject("Floating Portal Menu", new Type[4] { typeof(RectTransform), typeof(CanvasGroup), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); panel.transform.SetParent(val.transform, false); panelRect = (RectTransform)panel.transform; RectTransform obj = panelRect; RectTransform obj2 = panelRect; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); obj2.anchorMax = val3; obj.anchorMin = val3; panelRect.pivot = new Vector2(0.5f, 0.5f); canvasGroup = panel.GetComponent(); panelLayout = panel.GetComponent(); ((LayoutGroup)panelLayout).padding = new RectOffset(16, 16, 12, 12); ((HorizontalOrVerticalLayoutGroup)panelLayout).spacing = 4f; ((LayoutGroup)panelLayout).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)panelLayout).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)panelLayout).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)panelLayout).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)panelLayout).childForceExpandWidth = true; panel.GetComponent().verticalFit = (FitMode)2; darkBackdrop = CloneNativeDecoration("darken", panel.transform, 0); if (Object.op_Implicit((Object)(object)darkBackdrop)) { darkBackdropGroup = darkBackdrop.GetComponent() ?? darkBackdrop.AddComponent(); } menuOrnament = CloneNativeDecoration("ornament", panel.transform, 1); if (Object.op_Implicit((Object)(object)menuOrnament)) { menuOrnamentGraphics = menuOrnament.GetComponentsInChildren(true); menuOrnamentBaseAlphas = menuOrnamentGraphics.Select((Graphic graphic) => graphic.color.a).ToArray(); } titleText = (TMP_Text)(object)AddText(panel.transform, "CHOOSE DESTINATION", PortalVisualSettings.TitleFontSize, (FontStyles)0, PortalVisualSettings.TitleColor); hintText = (TMP_Text)(object)AddText(panel.transform, "Walk away or press Escape to close", PortalVisualSettings.HintFontSize, (FontStyles)0, PortalVisualSettings.HintColor); GameObject val4 = new GameObject("Destinations", new Type[3] { typeof(RectTransform), typeof(ScrollRect), typeof(LayoutElement) }); val4.transform.SetParent(panel.transform, false); scrollLayout = val4.GetComponent(); scrollLayout.preferredHeight = 320f; GameObject val5 = new GameObject("Viewport", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }); val5.transform.SetParent(val4.transform, false); Stretch((RectTransform)val5.transform); GameObject val6 = new GameObject("Content", new Type[2] { typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); val6.transform.SetParent(val5.transform, false); content = val6.transform; RectTransform val7 = (RectTransform)content; val7.anchorMin = new Vector2(0f, 1f); val7.anchorMax = new Vector2(1f, 1f); val7.pivot = new Vector2(0.5f, 1f); val7.anchoredPosition = Vector2.zero; val7.sizeDelta = Vector2.zero; contentLayout = val6.GetComponent(); ((HorizontalOrVerticalLayoutGroup)contentLayout).spacing = 2f; ((LayoutGroup)contentLayout).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)contentLayout).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)contentLayout).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)contentLayout).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)contentLayout).childForceExpandWidth = true; val6.GetComponent().verticalFit = (FitMode)2; destinationScroll = val4.GetComponent(); destinationScroll.viewport = (RectTransform)val5.transform; destinationScroll.content = val7; destinationScroll.horizontal = false; destinationScroll.vertical = true; destinationScroll.movementType = (MovementType)2; destinationScroll.scrollSensitivity = 32f; panel.SetActive(false); ApplyVisualSettings(); } private static GameObject CloneNativeDecoration(string name, Transform parent, int siblingIndex) { Menu instance = Menu.instance; object obj; if (instance == null) { obj = null; } else { Transform menuDialog = instance.m_menuDialog; obj = ((menuDialog != null) ? menuDialog.Find(name) : null); } Transform val = (Transform)obj; if (!Object.op_Implicit((Object)(object)val)) { return null; } GameObject val2 = Object.Instantiate(((Component)val).gameObject, parent, false); ((Object)val2).name = "Portal " + name; val2.SetActive(true); (val2.GetComponent() ?? val2.AddComponent()).ignoreLayout = true; Graphic[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } val2.transform.SetSiblingIndex(Mathf.Clamp(siblingIndex, 0, parent.childCount - 1)); return val2; } private void ApplyVisualSettings() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) visualsDirty = false; if (!Object.op_Implicit((Object)(object)panel)) { return; } panelRect.anchoredPosition = new Vector2(0f, PortalVisualSettings.PanelYOffset); panelRect.sizeDelta = new Vector2(PortalVisualSettings.PanelWidth, 0f); if (Object.op_Implicit((Object)(object)contentLayout)) { ((HorizontalOrVerticalLayoutGroup)contentLayout).spacing = PortalVisualSettings.RowSpacing; } if (Object.op_Implicit((Object)(object)destinationScroll)) { destinationScroll.scrollSensitivity = Mathf.Max(16f, PortalVisualSettings.RowHeight * 0.7f); } ApplyTextAppearance(titleText, PortalVisualSettings.TitleFontSize, PortalVisualSettings.TitleColor); ApplyTextAppearance(hintText, PortalVisualSettings.HintFontSize, PortalVisualSettings.HintColor); foreach (GameObject row in rows) { if (Object.op_Implicit((Object)(object)row)) { row.GetComponent()?.ApplyVisualSettings(); } } UpdateHintText(); if (Object.op_Implicit((Object)(object)darkBackdrop)) { darkBackdrop.SetActive(PortalVisualSettings.BackdropOpacity > 0.001f); if (Object.op_Implicit((Object)(object)darkBackdropGroup)) { darkBackdropGroup.alpha = PortalVisualSettings.BackdropOpacity; } } if (Object.op_Implicit((Object)(object)menuOrnament)) { menuOrnament.SetActive(PortalVisualSettings.ShowMenuOrnament); Color ornamentColor = PortalVisualSettings.OrnamentColor; for (int i = 0; i < menuOrnamentGraphics.Length; i++) { Graphic val = menuOrnamentGraphics[i]; if (Object.op_Implicit((Object)(object)val)) { val.color = new Color(ornamentColor.r, ornamentColor.g, ornamentColor.b, menuOrnamentBaseAlphas[i] * ornamentColor.a); } } } UpdateListHeight(); if (panel.activeSelf) { LayoutRebuilder.ForceRebuildLayoutImmediate(panelRect); } } private void UpdateListHeight() { if (Object.op_Implicit((Object)(object)scrollLayout)) { List list = rows.Where((GameObject row) => Object.op_Implicit((Object)(object)row) && row.activeSelf).ToList(); int num = Mathf.Max(1, list.Count); float num2 = list.Sum(delegate(GameObject row) { LayoutElement component = row.GetComponent(); return (component == null) ? PortalVisualSettings.RowHeight : component.preferredHeight; }) + (float)Mathf.Max(0, num - 1) * PortalVisualSettings.RowSpacing; float num3 = Mathf.Min(PortalVisualSettings.MaxListHeight, Mathf.Max(54f, PortalVisualSettings.RowHeight)); scrollLayout.preferredHeight = Mathf.Clamp(num2, num3, PortalVisualSettings.MaxListHeight); } } internal static void ApplyTextAppearance(TMP_Text text, float size, Color color) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) if (Object.op_Implicit((Object)(object)text)) { text.fontSize = size; ((Graphic)text).color = color; text.outlineColor = Color32.op_Implicit(PortalVisualSettings.OutlineColor); text.outlineWidth = PortalVisualSettings.OutlineWidth; } } private void ConfigureRowNavigation() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) List