Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterPortals v0.4.7
plugins/FraileyPortalSelector.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
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<PortalController>(); } ((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<float> titleFontSize; private static ConfigEntry<float> entryFontSize; private static ConfigEntry<float> hintFontSize; private static ConfigEntry<float> biomeFontSize; private static ConfigEntry<float> homeIconSize; private static ConfigEntry<string> titleColor; private static ConfigEntry<string> entryColor; private static ConfigEntry<string> hintColor; private static ConfigEntry<string> biomeColor; private static ConfigEntry<string> outlineColor; private static ConfigEntry<float> outlineWidth; private static ConfigEntry<float> hoverScale; private static ConfigEntry<float> hoverExpandSeconds; private static ConfigEntry<float> hoverContractSeconds; private static ConfigEntry<float> panelWidth; private static ConfigEntry<float> panelYOffset; private static ConfigEntry<float> rowHeight; private static ConfigEntry<float> rowSpacing; private static ConfigEntry<float> maxListHeight; private static ConfigEntry<float> backdropOpacity; private static ConfigEntry<string> ornamentColor; private static ConfigEntry<bool> showMenuOrnament; private static ConfigEntry<bool> showRowKnots; private static ConfigEntry<float> rowKnotGap; private static ConfigEntry<float> fadeInSeconds; private static ConfigEntry<float> fadeOutSeconds; private static ConfigEntry<float> triggerMultiplier; private static ConfigEntry<bool> showBiomeSubtitle; private static ConfigEntry<bool> preferHomeOnOpen; private static ConfigEntry<bool> showControlHints; private static ConfigEntry<KeyboardShortcut> 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<KeyCode>())); 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<bool>("Visual - Ornaments", "Show Menu Ornament", true, "Show Valheim's native menu ornament behind the selector."); showRowKnots = config.Bind<bool>("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<bool>("Portal List", "Show Biome Subtitle", true, "Show the portal's biome in smaller white text beneath its name."); preferHomeOnOpen = config.Bind<bool>("Portal List", "Prefer Home On Open", true, "Select and scroll to the Home portal when the list opens."); showControlHints = config.Bind<bool>("Portal List", "Show Control Hints", true, "Show short keyboard or controller instructions above the destination list."); setHomeKeyboardShortcut = config.Bind<KeyboardShortcut>("Portal List", "Set Home Keyboard Shortcut", new KeyboardShortcut((KeyCode)104, Array.Empty<KeyCode>()), "Keyboard shortcut that sets or clears Home on the selected destination."); MigrateLegacyVisualDefaults(config); Watch<float>(titleFontSize); Watch<float>(entryFontSize); Watch<float>(hintFontSize); Watch<float>(biomeFontSize); Watch<float>(homeIconSize); Watch<string>(titleColor); Watch<string>(entryColor); Watch<string>(hintColor); Watch<string>(biomeColor); Watch<string>(outlineColor); Watch<float>(outlineWidth); Watch<float>(hoverScale); Watch<float>(hoverExpandSeconds); Watch<float>(hoverContractSeconds); Watch<float>(panelWidth); Watch<float>(panelYOffset); Watch<float>(rowHeight); Watch<float>(rowSpacing); Watch<float>(maxListHeight); Watch<float>(backdropOpacity); Watch<string>(ornamentColor); Watch<bool>(showMenuOrnament); Watch<bool>(showRowKnots); Watch<float>(rowKnotGap); Watch<float>(fadeInSeconds); Watch<float>(fadeOutSeconds); Watch<float>(triggerMultiplier); Watch<bool>(showBiomeSubtitle); Watch<bool>(preferHomeOnOpen); Watch<bool>(showControlHints); Watch<KeyboardShortcut>(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<float> 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<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(minimum, maximum), Array.Empty<object>())); } private static ConfigEntry<string> 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<string>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>())); } private static void Watch<T>(ConfigEntry<T> entry) { entry.SettingChanged += OnSettingChanged; } private static void OnSettingChanged(object sender, EventArgs args) { PortalController.Instance?.MarkVisualsDirty(); } private static float Clamp(ConfigEntry<float> entry, float fallback, float minimum, float maximum) { return Mathf.Clamp(entry?.Value ?? fallback, minimum, maximum); } private static Color ParseColor(ConfigEntry<string> 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<string, string>(); } 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<ZDOID, long> Orders = new Dictionary<ZDOID, long>(); 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<ZDO> enumerable = ((instance != null) ? instance.GetPortalList() : null); Ensure(enumerable ?? Enumerable.Empty<ZDO>()); } } internal static void Ensure(IEnumerable<ZDO> 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<ZDOID, long> pair) => pair.Value).Select(delegate(KeyValuePair<ZDOID, long> 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<ZNetView>(); 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<PortalExitWatcher>() ?? ((Component)__instance).gameObject.AddComponent<PortalExitWatcher>()).Initialize(((Component)__instance).GetComponentInParent<TeleportWorld>(), __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<ZNetView>(); 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<Collider> localColliders = new HashSet<Collider>(); private TeleportWorld portal; private BoxCollider[] boxes = Array.Empty<BoxCollider>(); private Vector3[] originalBoxSizes = Array.Empty<Vector3>(); private SphereCollider[] spheres = Array.Empty<SphereCollider>(); private float[] originalSphereRadii = Array.Empty<float>(); private CapsuleCollider[] capsules = Array.Empty<CapsuleCollider>(); private float[] originalCapsuleRadii = Array.Empty<float>(); private float[] originalCapsuleHeights = Array.Empty<float>(); 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<BoxCollider>(); originalBoxSizes = boxes.Select((BoxCollider box) => box.size).ToArray(); spheres = ((Component)trigger).GetComponents<SphereCollider>(); originalSphereRadii = spheres.Select((SphereCollider sphere) => sphere.radius).ToArray(); capsules = ((Component)trigger).GetComponents<CapsuleCollider>(); 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<Player>() ?? ((Component)collider).GetComponentInParent<Player>(); 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<ZDOID> Destinations; internal ServerSession(ZDOID source, long nonce, float expires, IEnumerable<ZDOID> 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<ZDOID>(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<long, RequestWindow> Windows = new Dictionary<long, RequestWindow>(); private static readonly Dictionary<long, ServerSession> Sessions = new Dictionary<long, ServerSession>(); private static ZRoutedRpc registeredOn; internal static bool Register() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return false; } if (registeredOn == instance) { return true; } instance.Register<ZPackage>("com.fraileywoodworks.portalselector.v2.directory.request", (Action<long, ZPackage>)OnDirectoryRequest); instance.Register<ZPackage>("com.fraileywoodworks.portalselector.v2.directory.response", (Action<long, ZPackage>)OnDirectoryResponse); instance.Register<ZPackage>("com.fraileywoodworks.portalselector.v2.travel.request", (Action<long, ZPackage>)OnTravelRequest); instance.Register<ZPackage>("com.fraileywoodworks.portalselector.v2.travel.response", (Action<long, ZPackage>)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, bool>)((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<ZDO> list = (from z in ZDOMan.instance.GetPortalList() where z != null && z.IsValid() select z).ToList(); PortalOrderLedger.Ensure(list); List<PortalInfo> 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<PortalInfo> 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<PortalInfo> list = new List<PortalInfo>(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<Graphic>(); private float[] menuOrnamentBaseAlphas = Array.Empty<float>(); private bool visualsDirty; private readonly List<GameObject> rows = new List<GameObject>(); private readonly List<PortalEntryHover> portalRows = new List<PortalEntryHover>(); private readonly List<PortalInfo> currentPortals = new List<PortalInfo>(); 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<ZNetView>(); 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<PortalInfo> 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<string, int> dictionary = currentPortals.GroupBy<PortalInfo, string>((PortalInfo p) => p.Name, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, PortalInfo>, string, int>((IGrouping<string, PortalInfo> g) => g.Key, (IGrouping<string, PortalInfo> g) => g.Count(), StringComparer.OrdinalIgnoreCase); Dictionary<string, int> dictionary2 = new Dictionary<string, int>(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<Canvas>(); component.renderMode = (RenderMode)0; component.overrideSorting = true; RectTransform component2 = val.GetComponent<RectTransform>(); 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<Canvas>() : null); component.sortingOrder = (Object.op_Implicit((Object)(object)val2) ? (val2.sortingOrder + 1) : 1701); ConfigureScaler(val.GetComponent<CanvasScaler>()); 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<CanvasGroup>(); panelLayout = panel.GetComponent<VerticalLayoutGroup>(); ((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<ContentSizeFitter>().verticalFit = (FitMode)2; darkBackdrop = CloneNativeDecoration("darken", panel.transform, 0); if (Object.op_Implicit((Object)(object)darkBackdrop)) { darkBackdropGroup = darkBackdrop.GetComponent<CanvasGroup>() ?? darkBackdrop.AddComponent<CanvasGroup>(); } menuOrnament = CloneNativeDecoration("ornament", panel.transform, 1); if (Object.op_Implicit((Object)(object)menuOrnament)) { menuOrnamentGraphics = menuOrnament.GetComponentsInChildren<Graphic>(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<LayoutElement>(); 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<VerticalLayoutGroup>(); ((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<ContentSizeFitter>().verticalFit = (FitMode)2; destinationScroll = val4.GetComponent<ScrollRect>(); 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<GameObject>(((Component)val).gameObject, parent, false); ((Object)val2).name = "Portal " + name; val2.SetActive(true); (val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>()).ignoreLayout = true; Graphic[] componentsInChildren = val2.GetComponentsInChildren<Graphic>(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<PortalEntryHover>()?.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<GameObject> 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<LayoutElement>(); 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<Button> list = (from row in rows select (!Object.op_Implicit((Object)(object)row)) ? null : row.GetComponent<Button>() into button where Object.op_Implicit((Object)(object)button) && ((Selectable)button).interactable select button).ToList(); for (int num = 0; num < list.Count; num++) { Navigation navigation = ((Selectable)list[num]).navigation; ((Navigation)(ref navigation)).mode = (Mode)4; ((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)list[(num + list.Count - 1) % list.Count]; ((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)list[(num + 1) % list.Count]; ((Selectable)list[num]).navigation = navigation; } } private void SynchronizeInputSelection(bool centerMouse = false) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) EventSystem current = EventSystem.current; if (!Object.op_Implicit((Object)(object)current)) { return; } bool flag = ZInput.IsMouseActive(); if (previousMouseInput.HasValue && previousMouseInput.Value == flag) { return; } bool flag2 = previousMouseInput.HasValue && !previousMouseInput.Value && flag; previousMouseInput = flag; GameObject currentSelectedGameObject = current.currentSelectedGameObject; if (flag) { ApplySelectorCursor(centerMouse || flag2); if (centerMouse || flag2) { cursorCenterFrames = 1; openingMousePosition = new Vector3((float)Screen.width * 0.5f, (float)Screen.height * 0.5f, 0f); mouseChoiceArmed = false; } if (Object.op_Implicit((Object)(object)currentSelectedGameObject) && Object.op_Implicit((Object)(object)panel) && currentSelectedGameObject.transform.IsChildOf(panel.transform)) { current.SetSelectedGameObject((GameObject)null); } } else if (Object.op_Implicit((Object)(object)firstSelectable)) { ApplySelectorCursor(center: false); Button val = ((PortalVisualSettings.PreferHomeOnOpen && Object.op_Implicit((Object)(object)homeSelectable)) ? homeSelectable : firstSelectable); current.SetSelectedGameObject(((Component)val).gameObject); ScrollIntoView(((Component)val).gameObject); } UpdateHintText(); } private void AdvanceCursorCentering() { //IL_002e: 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) if (cursorCenterFrames > 0 && ZInput.IsMouseActive()) { ApplySelectorCursor(center: true); cursorCenterFrames--; if (cursorCenterFrames == 0) { openingMousePosition = Input.mousePosition; } } } private void ArmMouseChoiceAfterMovement() { //IL_0019: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!mouseChoiceArmed && cursorCenterFrames <= 0 && ZInput.IsMouseActive()) { Vector3 val = Input.mousePosition - openingMousePosition; if (((Vector3)(ref val)).sqrMagnitude > 9f) { mouseChoiceArmed = true; } } } private void KeepControllerSelectionVisible() { if (!ZInput.IsMouseActive() && Object.op_Implicit((Object)(object)destinationScroll) && Object.op_Implicit((Object)(object)destinationScroll.viewport) && Object.op_Implicit((Object)(object)destinationScroll.content)) { EventSystem current = EventSystem.current; GameObject selected = ((current != null) ? current.currentSelectedGameObject : null); ScrollIntoView(selected); } } private void ScrollIntoView(GameObject selected) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0082: 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) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)selected) && Object.op_Implicit((Object)(object)destinationScroll) && Object.op_Implicit((Object)(object)destinationScroll.viewport) && Object.op_Implicit((Object)(object)destinationScroll.content) && selected.transform.IsChildOf(content)) { Canvas.ForceUpdateCanvases(); Bounds val = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)destinationScroll.viewport, selected.transform); Rect rect = destinationScroll.viewport.rect; float num = 0f; if (((Bounds)(ref val)).min.y < ((Rect)(ref rect)).yMin) { num = ((Rect)(ref rect)).yMin - ((Bounds)(ref val)).min.y; } else if (((Bounds)(ref val)).max.y > ((Rect)(ref rect)).yMax) { num = ((Rect)(ref rect)).yMax - ((Bounds)(ref val)).max.y; } if (!Mathf.Approximately(num, 0f)) { Vector2 anchoredPosition = destinationScroll.content.anchoredPosition; anchoredPosition.y += num; destinationScroll.content.anchoredPosition = anchoredPosition; } } } private void ToggleHome(PortalInfo portal) { //IL_0016: 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_0034: 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_0071: Unknown result type (might be due to invalid IL or missing references) ZDOID id; bool flag = PortalHome.TryGet(out id) && id == portal.Id; if (!(flag ? PortalHome.Clear() : PortalHome.Set(portal.Id))) { return; } foreach (PortalEntryHover portalRow in portalRows) { portalRow.SetHome(!flag && portalRow.PortalId == portal.Id); } object obj; if (!flag) { PortalEntryHover? portalEntryHover = portalRows.FirstOrDefault((PortalEntryHover row) => row.PortalId == portal.Id); obj = ((portalEntryHover != null) ? ((Component)portalEntryHover).GetComponent<Button>() : null); } else { obj = null; } homeSelectable = (Button)obj; UpdateHintText(); Plugin.LogDebug(flag ? "Home portal cleared." : ("Home portal set to " + portal.Name + ".")); } private PortalEntryHover SelectedPortalRow() { EventSystem current = EventSystem.current; GameObject obj = ((current != null) ? current.currentSelectedGameObject : null); object obj2 = ((obj != null) ? obj.GetComponent<PortalEntryHover>() : null); if (obj2 == null) { obj2 = portalRows.FirstOrDefault((PortalEntryHover row) => row.PointerInside); if (obj2 == null) { if (!PortalVisualSettings.PreferHomeOnOpen || !Object.op_Implicit((Object)(object)homeSelectable)) { Button obj3 = firstSelectable; if (obj3 == null) { return null; } return ((Component)obj3).GetComponent<PortalEntryHover>(); } obj2 = ((Component)homeSelectable).GetComponent<PortalEntryHover>(); } } return (PortalEntryHover)obj2; } private void ToggleSelectedHome() { SelectedPortalRow()?.SetAsHome(); } private void ConfirmSelected() { if (!travelPending) { ((ZInput.IsMouseActive() && !mouseChoiceArmed && Object.op_Implicit((Object)(object)homeSelectable)) ? ((Component)homeSelectable).GetComponent<PortalEntryHover>() : SelectedPortalRow())?.Activate(); } } private void ActivateDestination(ZDOID destination) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SelectDestination(destination); } private void UpdateHintText() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)hintText)) { ((Component)hintText).gameObject.SetActive(PortalVisualSettings.ShowControlHints); if (PortalVisualSettings.ShowControlHints) { hintText.text = (ZInput.IsMouseActive() ? $"Enter Travel {PortalVisualSettings.SetHomeKeyboardShortcut} Set Home Esc Close" : "A Travel X Set Home B Close"); } } } private static void ShowStatus(string message) { MessageHud instance = MessageHud.instance; if (Object.op_Implicit((Object)(object)instance)) { instance.ShowMessage((MessageType)1, message, 0, ResolveHomeSprite(), false, false); } } internal static void ApplySelectorCursor(bool center) { if (Application.isBatchMode) { return; } if (!ZInput.IsMouseActive()) { if (ZCursor.IsVisible) { ZCursor.Hide(); } ZCursor.LockState = (CursorLockMode)1; return; } ZCursor.LockState = (CursorLockMode)0; if (!ZCursor.IsVisible) { ZCursor.Show(); } if (center) { CenterPointer(); } } private static void PrepareCursorWarp() { if (cursorWarpPrepared) { return; } cursorWarpPrepared = true; try { Type type = Acce