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 PortalSelector v1.0.1
Landoria.PortalSelector.dll
Decompiled 17 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using GUIFramework; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Landoria.PortalSelector")] [assembly: AssemblyDescription("Adds shared portal names and destinations to Valheim.")] [assembly: AssemblyCompany("Landoria")] [assembly: AssemblyProduct("Landoria.PortalSelector")] [assembly: AssemblyCopyright("Copyright © 2026 Landoria")] [assembly: ComVisible(false)] [assembly: Guid("E2FE30E1-DCF1-4BD7-9776-035DC9FAA2DF")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.1.13809")] [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 Landoria.PortalSelector { internal static class PlayerPortalCatalog { private const int Format = 1; internal static void Load(Player player, string key, Dictionary<Guid, PortalRecord> records) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!player.m_customData.TryGetValue(key, out var value) || string.IsNullOrEmpty(value)) { Plugin.DebugLog("Catalog: no saved data for this world."); return; } try { ZPackage val = new ZPackage(Convert.FromBase64String(value)); if (val.ReadInt() != 1) { Plugin.WarningLog("Catalog: unsupported format; ignoring saved data."); return; } int num = Mathf.Clamp(val.ReadInt(), 0, 10000); for (int i = 0; i < num; i++) { PortalRecord portalRecord = ReadRecord(val); if (portalRecord.Guid != Guid.Empty) { records[portalRecord.Guid] = portalRecord; } } Plugin.DebugLog("Catalog: loaded " + records.Count + " portals."); } catch (Exception ex) { records.Clear(); Plugin.WarningLog("Catalog: load failed (" + ex.GetType().Name + ")."); } } internal static void Save(Player player, string key, Dictionary<Guid, PortalRecord> records) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown try { ZPackage val = new ZPackage(); val.Write(1); val.Write(records.Count); foreach (PortalRecord value in records.Values) { WriteRecord(val, value); } player.m_customData[key] = Convert.ToBase64String(val.GetArray()); } catch (Exception ex) { Plugin.WarningLog("Catalog: save failed (" + ex.GetType().Name + ")."); } } private static PortalRecord ReadRecord(ZPackage package) { //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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) return new PortalRecord { Guid = Guid.Parse(package.ReadString()), LastKnownName = package.ReadString(), Position = package.ReadVector3(), Biome = (Biome)package.ReadInt() }; } private static void WriteRecord(ZPackage package, PortalRecord record) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected I4, but got Unknown package.Write(record.Guid.ToString("D")); package.Write(record.LastKnownName ?? ""); package.Write(record.Position); package.Write((int)record.Biome); } } internal static class PortalDirectory { private sealed class StartupEntry { internal readonly Guid Guid; internal readonly Vector3 Position; internal readonly bool Known; internal float FirstSync = -1f; internal int Syncs; internal StartupEntry(Guid guid, Vector3 position, bool known) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Guid = guid; Position = position; Known = known; } } private const string CatalogPrefix = "Landoria.PortalSelector.CatalogGuidV1."; private static readonly Dictionary<Guid, PortalRecord> Records = new Dictionary<Guid, PortalRecord>(); private static readonly Dictionary<ZDOID, Guid> SeenIds = new Dictionary<ZDOID, Guid>(); private static readonly HashSet<Guid> RemovedIds = new HashSet<Guid>(); private static Player _player; private static string _catalogKey; private static float _nextScan; private const float StartupTimeout = 5f; private const float StartupSpacing = 0.25f; private const int MaxStartupCandidates = 2048; private static readonly Queue<StartupEntry> StartupQueue = new Queue<StartupEntry>(); private static readonly HashSet<Guid> StartupScheduled = new HashSet<Guid>(); private static ZNet _startupSession; private static StartupEntry _startupCurrent; private static bool _startupRequested; private static bool _startupStarted; private static bool _startupCompleted; private static float _nextStartupCheck; private static int _startupChecked; private static int _startupRemoved; internal static void Update() { if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && ZDOMan.instance != null) { LoadSession(); if (Time.unscaledTime >= _nextScan) { Scan(); } UpdateStartupCleanup(); } } internal static void ScanNow() { _nextScan = 0f; Update(); } private static void Scan() { _nextScan = Time.unscaledTime + 5f; List<ZDO> portals = new List<ZDO>(ZDOMan.instance.GetPortalList()); if ((0u | (ScanObjects(portals) ? 1u : 0u) | (RefreshBiomes() ? 1u : 0u)) != 0) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); } } private static bool ScanObjects(List<ZDO> portals) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0034: 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_0042: Unknown result type (might be due to invalid IL or missing references) bool flag = false; HashSet<ZDOID> hashSet = new HashSet<ZDOID>(); for (int i = 0; i < portals.Count; i++) { ZDO val = portals[i]; if (!hashSet.Add(val.m_uid)) { continue; } flag |= ScanPortal(val); ZDOID connectionZDOID = val.GetConnectionZDOID((ConnectionType)1); if (!(connectionZDOID == ZDOID.None)) { ZDO target = PortalConnection.GetTarget(connectionZDOID); if (target != null) { portals.Add(target); } } } return flag; } private static bool ScanPortal(ZDO portal) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) PortalFields.EnsureIdentity(portal.m_uid); PortalRecord portalRecord = CreateRecord(portal); if (portalRecord == null) { return false; } int num; if (!Records.ContainsKey(portalRecord.Guid)) { num = ((!RemovedIds.Contains(portalRecord.Guid)) ? 1 : 0); if (num != 0) { PortalVanillaImport.TryImport(portal, portalRecord); } } else { num = 0; } bool result = UpdateRecord(portal); if (num != 0 && Records.TryGetValue(portalRecord.Guid, out var value)) { PortalPeerSync.AnnouncePortal(portal.m_uid, value); } return result; } private static bool RefreshBiomes() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (WorldGenerator.instance == null) { return false; } bool result = false; foreach (PortalRecord value in Records.Values) { Biome val = ResolveBiome(value.Position); if (value.Biome != val) { value.Biome = val; result = true; } } return result; } internal static float NearestOtherPortalDistanceSquared(PortalRecord record, PortalRecord partner) { float num = float.PositiveInfinity; foreach (PortalRecord value in Records.Values) { if (!(value.Guid == record.Guid) && (partner == null || !(value.Guid == partner.Guid))) { float num2 = record.Position.x - value.Position.x; float num3 = record.Position.z - value.Position.z; num = Math.Min(num, num2 * num2 + num3 * num3); } } return num; } internal static PortalRecord Find(Guid guid) { LoadSession(); Records.TryGetValue(guid, out var value); return value; } internal static PortalRecord Find(ZDOID id) { //IL_0005: 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) LoadSession(); PortalZdoData portalZdoData = PortalFields.Read(id); if (portalZdoData != null && portalZdoData.Guid != Guid.Empty) { return Find(portalZdoData.Guid); } if (!SeenIds.TryGetValue(id, out var value)) { return null; } return Find(value); } internal static bool Remember(ZDO portal) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) LoadSession(); if ((Object)(object)_player == (Object)null || portal == null) { return false; } PortalFields.EnsureIdentity(portal.m_uid); PortalRecord portalRecord = CreateRecord(portal); if (portalRecord == null) { return false; } int num; if (!Records.ContainsKey(portalRecord.Guid)) { num = ((!RemovedIds.Contains(portalRecord.Guid)) ? 1 : 0); if (num != 0) { PortalVanillaImport.TryImport(portal, portalRecord); } } else { num = 0; } if (UpdateRecord(portal)) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); } if (num != 0 && Records.TryGetValue(portalRecord.Guid, out var value)) { PortalPeerSync.AnnouncePortal(portal.m_uid, value); } return true; } internal static List<PortalRecord> KnownRecords() { LoadSession(); return new List<PortalRecord>(Records.Values); } internal static void CacheName(ZDOID id, string name) { //IL_001a: 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_0062: Unknown result type (might be due to invalid IL or missing references) LoadSession(); if ((Object)(object)_player == (Object)null || string.IsNullOrWhiteSpace(name)) { return; } PortalRecord portalRecord = Find(id); if (portalRecord != null && !(portalRecord.LastKnownName == name)) { portalRecord.LastKnownName = name; PlayerPortalCatalog.Save(_player, _catalogKey, Records); ZDO target = PortalConnection.GetTarget(id); if (target != null && target.IsOwner()) { PortalPeerSync.AnnouncePortal(id, portalRecord); } } } private static void LoadSession() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)localPlayer == (Object)null)) { string text = "Landoria.PortalSelector.CatalogGuidV1." + ZNet.instance.GetWorldUID(); if (_player != localPlayer || !(_catalogKey == text)) { _player = localPlayer; _catalogKey = text; _nextScan = 0f; Records.Clear(); SeenIds.Clear(); RemovedIds.Clear(); PlayerDestinations.Reset(); PortalConnection.Reset(); PlayerPortalCatalog.Load(localPlayer, text, Records); Plugin.DebugLog("Catalog: world session ready, records=" + Records.Count + "."); } } } private static bool UpdateRecord(ZDO portal) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) PortalRecord portalRecord = CreateRecord(portal); if (portalRecord == null) { return false; } if (RemovedIds.Contains(portalRecord.Guid)) { return false; } SeenIds[portal.m_uid] = portalRecord.Guid; return StoreRecord(portalRecord); } internal static PortalRecord CreateRecord(ZDO portal) { //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_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (portal == null) { return null; } if (WorldGenerator.instance == null) { return null; } PortalZdoData portalZdoData = PortalFields.Read(portal); if (portalZdoData.Guid == Guid.Empty) { return null; } Vector3 position = portalZdoData.Position; return new PortalRecord { Guid = portalZdoData.Guid, LastKnownName = portalZdoData.Name, Position = position, Biome = ResolveBiome(position) }; } private static bool StoreRecord(PortalRecord record) { //IL_0045: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) PortalRecord value; bool num = Records.TryGetValue(record.Guid, out value); if (num && string.IsNullOrWhiteSpace(record.LastKnownName)) { record.LastKnownName = value.LastKnownName; } bool result = !num || value.LastKnownName != record.LastKnownName || value.Position != record.Position || value.Biome != record.Biome; Records[record.Guid] = record; if (!num) { Guid guid = record.Guid; Plugin.DebugLog("Catalog: discovered guid=" + guid.ToString() + "."); } return result; } private static Biome ResolveBiome(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0016: Unknown result type (might be due to invalid IL or missing references) Biome val = Heightmap.FindBiome(position); if ((int)val == 0) { return WorldGenerator.instance.GetBiomeSector(position, false).Biome; } return val; } internal unsafe static void OnDestroyedZDO(ZDOMan manager, ZDOID id) { //IL_002a: 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_0075: 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_009d: 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) Player localPlayer = Player.m_localPlayer; ZNet instance = ZNet.instance; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null) && manager == ZDOMan.instance) { LoadSession(); Guid guid = Find(id)?.Guid ?? PortalFields.Read(id)?.Guid ?? Guid.Empty; if (guid == Guid.Empty && SeenIds.TryGetValue(id, out var value)) { guid = value; } SeenIds.Remove(id); if (!(guid == Guid.Empty) && RemovePortal(guid)) { PortalPeerSync.AnnounceRemoval(guid); ZDOID val = id; Plugin.DebugLog("Catalog: destroyed portal removed zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + "."); } } } internal static void OnPeerRemoval(Guid guid) { LoadSession(); if ((Object)(object)_player != (Object)null && RemovePortal(guid)) { Guid guid2 = guid; Plugin.DebugLog("Catalog: peer removed guid=" + guid2.ToString() + "."); } } private static bool RemovePortal(Guid guid) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) if (guid == Guid.Empty || !RemovedIds.Add(guid)) { return false; } PlayerDestinations.ForgetPortal(guid); List<ZDOID> list = new List<ZDOID>(); foreach (KeyValuePair<ZDOID, Guid> seenId in SeenIds) { if (seenId.Value == guid) { list.Add(seenId.Key); } } foreach (ZDOID item in list) { SeenIds.Remove(item); } if (Records.Remove(guid)) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); } PortalDialog.OnPortalRemoved(guid); return true; } internal static void OnPeerPortal(ZDOID id, Guid guid, string name, Vector3 position) { //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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) LoadSession(); if (!((Object)(object)_player == (Object)null) && WorldGenerator.instance != null && !RemovedIds.Contains(guid)) { if (id != ZDOID.None) { SeenIds[id] = guid; } if (StoreRecord(new PortalRecord { Guid = guid, LastKnownName = name, Position = position, Biome = ResolveBiome(position) })) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); PortalDialog.OnPortalUpdated(Records[guid]); Guid guid2 = guid; Plugin.DebugLog("Catalog: peer portal guid=" + guid2.ToString() + "."); } } } internal static void Request(ZDOID origin) { //IL_0005: 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) //IL_002e: Unknown result type (might be due to invalid IL or missing references) ScanNow(); if (Find(origin) == null || !PlayerPortalNames.IsNamed(origin)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Name this portal before choosing a destination.", 0, (Sprite)null, false); } } else { PortalDialog.Open(origin, Records.Values.Where((PortalRecord record) => !string.IsNullOrWhiteSpace(record.LastKnownName)).ToList()); } } internal static void BeginStartupCleanup() { if ((Object)(object)_startupSession != (Object)(object)ZNet.instance) { ResetStartupCleanup(); _startupSession = ZNet.instance; } if (!_startupStarted && !_startupCompleted) { _startupRequested = true; Plugin.DebugLog("Startup: first spawn requested catalog check."); } } internal static void ResetStartupCleanup() { StartupQueue.Clear(); StartupScheduled.Clear(); _startupSession = null; _startupCurrent = null; _startupRequested = false; _startupStarted = false; _startupCompleted = false; _startupChecked = 0; _startupRemoved = 0; } private static void UpdateStartupCleanup() { if (!_startupRequested && !_startupStarted) { return; } if ((Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)_player != (Object)(object)Player.m_localPlayer) { ResetStartupCleanup(); return; } if (_startupRequested && WorldGenerator.instance != null) { StartStartupCleanup(); } if (_startupStarted) { if (_startupCurrent != null) { CheckStartupCurrent(); } else if (Time.unscaledTime >= _nextStartupCheck) { DispatchStartupCheck(); } if (_startupCurrent == null && StartupQueue.Count == 0) { FinishStartupCleanup(); } } } private static void StartStartupCleanup() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) _startupRequested = false; _startupStarted = true; _nextStartupCheck = Time.unscaledTime; foreach (PortalRecord value in Records.Values) { ScheduleStartupCheck(value.Guid, value.Position, known: true); } Plugin.DebugLog("Startup: checking " + StartupQueue.Count + " saved portals."); PortalPeerSync.RequestSnapshot(); } private static void DispatchStartupCheck() { //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) if (StartupQueue.Count == 0) { return; } _startupCurrent = StartupQueue.Dequeue(); string[] obj = new string[7] { "Startup: checking guid=", _startupCurrent.Guid.ToString(), " known=", null, null, null, null }; bool known = _startupCurrent.Known; obj[3] = known.ToString(); obj[4] = " near="; obj[5] = ((object)_startupCurrent.Position/*cast due to .constrained prefix*/).ToString(); obj[6] = "."; Plugin.DebugLog(string.Concat(obj)); if (_startupCurrent.Known && !Records.ContainsKey(_startupCurrent.Guid)) { Plugin.DebugLog("Startup: skipped removed guid=" + _startupCurrent.Guid.ToString() + "."); ReleaseStartupCheck(); return; } ZDO val = PortalConnection.FindLoaded(_startupCurrent.Guid); if (val != null) { ConfirmStartupPortal(val); ReleaseStartupCheck(); } else if (ZNet.instance.IsServer()) { Plugin.DebugLog("Startup: host has no matching portal guid=" + _startupCurrent.Guid.ToString() + "."); ExpireStartupCheck(); ReleaseStartupCheck(); } } private static void CheckStartupCurrent() { if (_startupCurrent.Known && !Records.ContainsKey(_startupCurrent.Guid)) { ReleaseStartupCheck(); return; } ZDO val = PortalConnection.FindLoaded(_startupCurrent.Guid); Vector3 position; if (val != null) { ConfirmStartupPortal(val); ReleaseStartupCheck(); } else if (PortalConnection.TryGetInterest(out position)) { if (_startupCurrent.FirstSync >= 0f) { Plugin.DebugLog("Startup: travel paused check guid=" + _startupCurrent.Guid.ToString() + "."); } _startupCurrent.FirstSync = -1f; _startupCurrent.Syncs = 0; } else if (_startupCurrent.FirstSync >= 0f && _startupCurrent.Syncs >= 2 && Time.unscaledTime - _startupCurrent.FirstSync >= 5f) { ExpireStartupCheck(); ReleaseStartupCheck(); } } internal static bool TryGetStartupInterest(out Vector3 position) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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) position = Vector3.zero; if (_startupCurrent == null || (Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return false; } position = (Records.TryGetValue(_startupCurrent.Guid, out var value) ? value.Position : _startupCurrent.Position); return true; } internal static void MarkStartupInterestSent() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (_startupCurrent != null) { if (_startupCurrent.FirstSync < 0f) { _startupCurrent.FirstSync = Time.unscaledTime; Plugin.DebugLog("Startup: requesting guid=" + _startupCurrent.Guid.ToString() + " near=" + ((object)_startupCurrent.Position/*cast due to .constrained prefix*/).ToString() + "."); } _startupCurrent.Syncs++; Plugin.DebugLog("Startup: area sync guid=" + _startupCurrent.Guid.ToString() + " count=" + _startupCurrent.Syncs + "."); } } private unsafe static void ConfirmStartupPortal(ZDO portal) { //IL_006c: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) PortalZdoData portalZdoData = PortalFields.Read(portal); PortalRecord value; string text = (Records.TryGetValue(portalZdoData.Guid, out value) ? value.LastKnownName : null); if (!Remember(portal)) { return; } PortalRecord portalRecord = Find(portalZdoData.Guid); string[] obj = new string[9] { "Startup: live portal guid=", null, null, null, null, null, null, null, null }; Guid guid = portalZdoData.Guid; obj[1] = guid.ToString(); obj[2] = " zdo="; ZDOID uid = portal.m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = " name='"; obj[5] = portalRecord?.LastKnownName; obj[6] = "' position="; obj[7] = (portalRecord?.Position).ToString(); obj[8] = "."; Plugin.DebugLog(string.Concat(obj)); if (portalRecord != null && text != portalRecord.LastKnownName) { PortalDialog.OnPortalUpdated(portalRecord); guid = portalZdoData.Guid; Plugin.DebugLog("Startup: refreshed name guid=" + guid.ToString() + "."); if (value != null) { PortalPeerSync.AnnouncePortal(portal.m_uid, portalRecord); } } Guid guid2 = PlayerDestinations.Get(portal.m_uid); if (guid2 != Guid.Empty && guid2 != portalZdoData.Guid) { ScheduleStartupCheck(guid2, portalZdoData.DestinationPosition, Records.ContainsKey(guid2)); } string[] obj2 = new string[5] { "Startup: confirmed guid=", null, null, null, null }; guid = portalZdoData.Guid; obj2[1] = guid.ToString(); obj2[2] = " route="; guid = guid2; obj2[3] = guid.ToString(); obj2[4] = "."; Plugin.DebugLog(string.Concat(obj2)); } private unsafe static void ScheduleStartupCheck(Guid guid, Vector3 position, bool known) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (guid != Guid.Empty && StartupScheduled.Add(guid)) { StartupQueue.Enqueue(new StartupEntry(guid, position, known)); string[] obj = new string[9] { "Startup: queued guid=", null, null, null, null, null, null, null, null }; Guid guid2 = guid; obj[1] = guid2.ToString(); obj[2] = " known="; obj[3] = known.ToString(); obj[4] = " near="; Vector3 val = position; obj[5] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[6] = " pending="; obj[7] = StartupQueue.Count.ToString(); obj[8] = "."; Plugin.DebugLog(string.Concat(obj)); } } internal static void QueueStartupCandidate(Guid guid, Vector3 position) { //IL_0143: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)_player == (Object)null || (!_startupStarted && !_startupCompleted)) { Guid guid2 = guid; Plugin.DebugLog("Startup: ignored peer guid=" + guid2.ToString() + " because catalog check is not ready."); } else if (Records.ContainsKey(guid) || RemovedIds.Contains(guid) || StartupScheduled.Contains(guid) || StartupScheduled.Count >= 2048) { string[] obj = new string[11] { "Startup: ignored peer guid=", null, null, null, null, null, null, null, null, null, null }; Guid guid2 = guid; obj[1] = guid2.ToString(); obj[2] = " known="; obj[3] = Records.ContainsKey(guid).ToString(); obj[4] = " removed="; obj[5] = RemovedIds.Contains(guid).ToString(); obj[6] = " queued="; obj[7] = StartupScheduled.Contains(guid).ToString(); obj[8] = " limit="; obj[9] = (StartupScheduled.Count >= 2048).ToString(); obj[10] = "."; Plugin.DebugLog(string.Concat(obj)); } else { ScheduleStartupCheck(guid, position, known: false); if (_startupCompleted && StartupQueue.Count > 0) { Plugin.DebugLog("Startup: resumed check for peer portals."); _startupCompleted = false; _startupStarted = true; _nextStartupCheck = Time.unscaledTime; } } } private static void ExpireStartupCheck() { Guid guid = _startupCurrent.Guid; bool flag = _startupCurrent.Known && Records.Remove(guid); if (flag) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); PortalDialog.OnPortalRemoved(guid); _startupRemoved++; } string[] obj = new string[9] { "Startup: unanswered guid=", null, null, null, null, null, null, null, null }; Guid guid2 = guid; obj[1] = guid2.ToString(); obj[2] = " known="; bool known = _startupCurrent.Known; obj[3] = known.ToString(); obj[4] = " syncs="; obj[5] = _startupCurrent.Syncs.ToString(); obj[6] = " removed="; obj[7] = flag.ToString(); obj[8] = "."; Plugin.DebugLog(string.Concat(obj)); } private static void ReleaseStartupCheck() { _startupCurrent = null; _startupChecked++; _nextStartupCheck = Time.unscaledTime + 0.25f; } private static void FinishStartupCleanup() { _startupStarted = false; _startupCompleted = true; Plugin.DebugLog("Startup: complete checked=" + _startupChecked + " removed=" + _startupRemoved + "."); } internal static void OnUnresponsive(Guid destination, ZDOID origin) { //IL_001f: 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) LoadSession(); if ((Object)(object)_player == (Object)null || destination == Guid.Empty) { return; } PortalZdoData portalZdoData = PortalFields.Read(origin); if (portalZdoData != null && !(portalZdoData.DestinationGuid != destination)) { PlayerDestinations.ClearUnresponsive(origin, destination); bool flag = Records.Remove(destination); if (flag) { PlayerPortalCatalog.Save(_player, _catalogKey, Records); PortalDialog.OnPortalRemoved(destination); } PortalConnection.StopWaiting(destination); ((Character)_player).Message((MessageType)2, flag ? "Destination portal did not respond and was removed from your list." : "Destination portal did not respond.", 0, (Sprite)null, false); string[] obj = new string[5] { "Catalog: unresponsive guid=", null, null, null, null }; Guid guid = destination; obj[1] = guid.ToString(); obj[2] = " removed="; obj[3] = flag.ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } } } internal sealed class PortalRecord { internal Guid Guid; internal string LastKnownName; internal Vector3 Position; internal Biome Biome; } internal static class PortalVanillaImport { internal unsafe static bool TryImport(ZDO portal, PortalRecord source) { //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_0014: 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) //IL_0038: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) if (portal == null || source == null) { return false; } ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1); PortalRecord portalRecord = null; ZDO val = null; if (connectionZDOID != ZDOID.None && PortalFields.Read(portal).DestinationGuid == Guid.Empty) { val = PortalConnection.GetTarget(connectionZDOID); if (val != null) { PortalFields.EnsureIdentity(connectionZDOID); } portalRecord = PortalDirectory.CreateRecord(val); if (portalRecord == null) { PortalConnection.Request(connectionZDOID); } } if (!PlayerPortalNames.ImportFromShared(portal, source, portalRecord)) { return false; } bool flag = false; if (portalRecord != null && source.Guid != portalRecord.Guid && Named(portal) && Named(val)) { if (!PortalFields.Claim(portal.m_uid) || !PortalFields.SetDestination(portal.m_uid, portalRecord.Guid, portalRecord.Position)) { return false; } flag = true; } string[] obj = new string[7] { "Vanilla import: zdo=", null, null, null, null, null, null }; ZDOID uid = portal.m_uid; obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[2] = " partner="; obj[3] = ((val == null) ? "none" : ((object)Unsafe.As<ZDOID, ZDOID>(ref val.m_uid)/*cast due to .constrained prefix*/).ToString()); obj[4] = " routeImported="; obj[5] = flag.ToString(); obj[6] = "."; Plugin.DebugLog(string.Concat(obj)); return true; } private static bool Named(ZDO portal) { if (portal != null) { if (string.IsNullOrWhiteSpace(PortalFields.Read(portal).Name)) { return !string.IsNullOrWhiteSpace(portal.GetString(ZDOVars.s_tag, "")); } return true; } return false; } } [BepInPlugin("Landoria.PortalSelector", "PortalSelector", "1.0.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "Landoria.PortalSelector"; public const string PluginName = "PortalSelector"; public const string PluginVersion = "1.0.1"; private static ManualLogSource _logger; private Harmony _harmony; internal static void DebugLog(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogDebug((object)message); } } internal static void WarningLog(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)message); } } private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown _logger = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"PortalSelector 1.0.1 loaded."); _harmony = new Harmony("Landoria.PortalSelector"); _harmony.PatchAll(); Game.m_playerInitialSpawn += PortalDirectory.BeginStartupCleanup; } private void Update() { PortalPeerSync.Update(); PortalDirectory.Update(); } private void OnDestroy() { Game.m_playerInitialSpawn -= PortalDirectory.BeginStartupCleanup; PortalDirectory.ResetStartupCleanup(); PortalPeerSync.Reset(); PortalConnection.Reset(); PlayerDestinations.Reset(); PortalNameConfirmPatch.Dispose(); PortalDialog.Close(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _logger = null; } } internal static class PlayerDestinations { private static readonly Dictionary<ZDOID, string> LastResolution = new Dictionary<ZDOID, string>(); private static readonly Dictionary<ZDOID, Guid> SuppressedRoutes = new Dictionary<ZDOID, Guid>(); internal static void Reset() { LastResolution.Clear(); SuppressedRoutes.Clear(); } internal static Guid Get(ZDOID origin) { //IL_0000: 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) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0072: Unknown result type (might be due to invalid IL or missing references) if (PortalDirectory.Find(origin) == null || !PlayerPortalNames.IsNamed(origin)) { return Guid.Empty; } PortalZdoData portalZdoData = PortalFields.Read(origin); Guid guid = portalZdoData?.DestinationGuid ?? Guid.Empty; if (guid == Guid.Empty || guid == portalZdoData.Guid || (SuppressedRoutes.TryGetValue(origin, out var value) && value == guid)) { Trace(origin, "no selection"); return Guid.Empty; } Guid guid2 = guid; Trace(origin, "target=" + guid2); return guid; } internal unsafe static bool Set(ZDOID origin, Guid destination) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0069: 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) PortalRecord portalRecord = PortalDirectory.Find(origin); PortalRecord portalRecord2 = PortalDirectory.Find(destination); if (portalRecord == null || portalRecord2 == null || portalRecord.Guid == destination || !PlayerPortalNames.IsNamed(origin) || string.IsNullOrWhiteSpace(portalRecord2.LastKnownName) || !PortalFields.Claim(origin) || !PlayerPortalNames.EnsureStored(origin) || !PortalFields.SetDestination(origin, destination, portalRecord2.Position)) { return false; } string[] obj = new string[5] { "Route: saved on source zdo=", null, null, null, null }; ZDOID val = origin; obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " targetGuid="; Guid guid = destination; obj[3] = guid.ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); SuppressedRoutes.Remove(origin); return true; } internal static void ClearUnresponsive(ZDOID origin, Guid destination) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_0052: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) PortalZdoData portalZdoData = PortalFields.Read(origin); if (portalZdoData != null && !(portalZdoData.DestinationGuid != destination)) { SuppressedRoutes[origin] = destination; if (PortalFields.Claim(origin) && PortalFields.SetDestination(origin, Guid.Empty, Vector3.zero)) { SuppressedRoutes.Remove(origin); } LastResolution.Remove(origin); } } internal static void ForgetPortal(Guid destroyed) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) int num = 0; if (ZDOMan.instance != null) { foreach (ZDO portal in ZDOMan.instance.GetPortalList()) { if (portal.IsOwner() && PortalFields.Read(portal).DestinationGuid == destroyed && PortalFields.SetDestination(portal.m_uid, Guid.Empty, Vector3.zero)) { num++; } } } LastResolution.Clear(); if (num > 0) { string[] obj = new string[5] { "Route: cleared ", num.ToString(), " local routes to destroyed guid=", null, null }; Guid guid = destroyed; obj[3] = guid.ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } } private unsafe static void Trace(ZDOID source, string state) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) if (!LastResolution.TryGetValue(source, out var value) || !(value == state)) { LastResolution[source] = state; string[] obj = new string[5] { "Route: source=", null, null, null, null }; ZDOID val = source; obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " "; obj[3] = state; obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } } } internal static class PlayerPortalNames { internal const int MaxLength = 50; internal const string DuplicateNameMessage = "This name is already used by another portal."; internal static string Get(ZDOID id) { //IL_0000: 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_003a: Unknown result type (might be due to invalid IL or missing references) PortalRecord portalRecord = PortalDirectory.Find(id); ZDO target = PortalConnection.GetTarget(id); string text = PortalFields.Read(target)?.Name; if (!string.IsNullOrWhiteSpace(text)) { if (portalRecord != null && portalRecord.LastKnownName != text) { PortalDirectory.CacheName(id, text); } return text; } if (!string.IsNullOrWhiteSpace(portalRecord?.LastKnownName)) { return portalRecord.LastKnownName; } return ((target != null) ? target.GetString(ZDOVars.s_tag, "") : null) ?? ""; } internal static string Get(Guid guid) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) PortalRecord portalRecord = PortalDirectory.Find(guid); if (portalRecord == null) { return ""; } ZDO val = PortalConnection.FindLoaded(guid); if (val != null) { return Get(val.m_uid); } return portalRecord.LastKnownName ?? ""; } internal static bool IsNamed(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return !string.IsNullOrWhiteSpace(Get(id)); } internal unsafe static bool Set(ZDOID id, string name) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || PortalConnection.GetTarget(id) == null) { return false; } string text = name?.Trim() ?? ""; if (text.Length > 50) { text = text.Substring(0, 50); } if (string.IsNullOrWhiteSpace(text)) { return false; } if (InUse(id, text)) { ((Character)localPlayer).Message((MessageType)2, "This name is already used by another portal.", 0, (Sprite)null, false); return false; } if (!PortalFields.Claim(id) || !PortalFields.SetName(id, text)) { ((Character)localPlayer).Message((MessageType)2, "Could not save the portal name.", 0, (Sprite)null, false); return false; } PortalDirectory.CacheName(id, text); ZDOID val = id; Plugin.DebugLog("Name: saved on zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + "."); return true; } internal static bool NameExists(ZDOID id, string name) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null && PortalConnection.GetTarget(id) != null) { return InUse(id, name?.Trim() ?? ""); } return false; } internal static bool EnsureStored(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(PortalFields.Read(id)?.Name)) { return true; } string text = Get(id).Trim(); if (string.IsNullOrWhiteSpace(text)) { return false; } if (InUse(id, text)) { Guid own = PortalDirectory.Find(id)?.Guid ?? Guid.Empty; HashSet<string> used = new HashSet<string>(from other in PortalDirectory.KnownRecords() where other.Guid != own select Get(other.Guid), StringComparer.OrdinalIgnoreCase); text = UniqueName(text, used); } if (!PortalFields.SetName(id, text)) { return false; } PortalDirectory.CacheName(id, text); return true; } internal static bool ImportFromShared(ZDO portal, PortalRecord record, PortalRecord partner) { //IL_0013: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (portal == null) { return false; } ZDOID uid = portal.m_uid; string text = portal.GetString(ZDOVars.s_tag, ""); if (string.IsNullOrWhiteSpace(text) || !string.IsNullOrWhiteSpace(PortalFields.Read(portal).Name)) { return true; } if (!PortalFields.Claim(uid)) { return false; } string text2 = InitialName(record, partner, text); if (InUse(uid, text2)) { HashSet<string> used = new HashSet<string>(from other in PortalDirectory.KnownRecords() where other.Guid != record.Guid select Get(other.Guid), StringComparer.OrdinalIgnoreCase); text2 = UniqueName(text2, used); } if (!PortalFields.SetName(uid, text2)) { return false; } PortalDirectory.CacheName(uid, text2); return true; } private static string InitialName(PortalRecord record, PortalRecord partner, string tag) { string text = ""; if (partner != null) { float num = PortalDirectory.NearestOtherPortalDistanceSquared(record, partner); float num2 = PortalDirectory.NearestOtherPortalDistanceSquared(partner, record); bool flag = num < 10000f; bool flag2 = num2 < 10000f; text = (((flag != flag2) ? flag : ((flag && num != num2) ? (num < num2) : (!IsFirst(record, partner)))) ? "_2" : ""); } tag = tag.Trim(); int num3 = 50 - text.Length; if (tag.Length <= num3) { return tag + text; } return tag.Substring(0, num3) + text; } private static bool InUse(ZDOID id, string name) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) Guid own = PortalDirectory.Find(id)?.Guid ?? Guid.Empty; if (!string.IsNullOrWhiteSpace(name)) { return PortalDirectory.KnownRecords().Any((PortalRecord other) => other.Guid != own && string.Equals(Get(other.Guid), name, StringComparison.OrdinalIgnoreCase)); } return false; } private static string UniqueName(string proposed, HashSet<string> used) { int num = 2; string text2; while (true) { string text = " (" + num + ")"; text2 = proposed.Substring(0, Math.Min(proposed.Length, 50 - text.Length)).TrimEnd(Array.Empty<char>()) + text; if (!used.Contains(text2)) { break; } num++; } return text2; } private static bool IsFirst(PortalRecord record, PortalRecord partner) { return record.Guid.CompareTo(partner.Guid) < 0; } } internal static class PortalConnection { private static readonly Dictionary<ZDOID, float> Requests = new Dictionary<ZDOID, float>(); private static readonly HashSet<ZDOID> TrackedRequests = new HashSet<ZDOID>(); private static Guid _interestGuid; private static Vector3 _interestPosition; private static float _interestStarted; private static float _interestUntil; private static int _interestSyncs; private const float ResponseTimeout = 5f; internal static void Reset() { Requests.Clear(); TrackedRequests.Clear(); _interestGuid = Guid.Empty; _interestSyncs = 0; } internal static ZDO GetTarget(ZDOID id) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(id) : null); if (val == null || (Object)(object)Game.instance == (Object)null || !Game.instance.PortalPrefabHash.Contains(val.GetPrefab())) { return null; } return val; } internal unsafe static ZDO GetConfirmedTarget(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) ZDO target = GetTarget(id); if (target == null) { return null; } if (TrackedRequests.Remove(id)) { ZDOID val = id; Plugin.DebugLog("ZDO: received portal zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + "."); } return target; } internal static ZDO FindLoaded(Guid guid) { if (guid == Guid.Empty || ZDOMan.instance == null) { return null; } foreach (ZDO portal in ZDOMan.instance.GetPortalList()) { if (PortalFields.Read(portal).Guid == guid) { return portal; } } return null; } internal unsafe static ZDO GetConfirmedTarget(Guid guid, Vector3 position, bool focus = true) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (guid == Guid.Empty) { return null; } ZDO val = FindLoaded(guid); if (val != null) { if (_interestGuid == guid) { _interestGuid = Guid.Empty; string[] obj = new string[5] { "ZDO: resolved guid=", null, null, null, null }; Guid guid2 = guid; obj[1] = guid2.ToString(); obj[2] = " zdo="; ZDOID uid = val.m_uid; obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } return val; } if (focus) { Focus(guid, position); } return null; } internal static bool TargetFound(Guid guid, Vector3 position, bool focus) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetConfirmedTarget(guid, position, focus) != null; } internal static bool TryGetInterest(out Vector3 position) { //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) position = _interestPosition; if (_interestGuid != Guid.Empty) { return Time.unscaledTime <= _interestUntil; } return false; } internal static void MarkInterestSent() { _interestSyncs++; } internal static bool TimedOut(Guid guid, Vector3 position) { //IL_001a: 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) if (guid != Guid.Empty && _interestGuid == guid && _interestPosition == position && (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) || _interestSyncs >= 2)) { return Time.unscaledTime - _interestStarted >= 5f; } return false; } internal static void StopWaiting(Guid guid) { if (_interestGuid == guid) { _interestGuid = Guid.Empty; _interestSyncs = 0; } } private unsafe static void Focus(Guid guid, Vector3 position) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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) if (_interestGuid != guid || _interestPosition != position || Time.unscaledTime > _interestUntil) { _interestStarted = Time.unscaledTime; _interestSyncs = 0; string[] obj = new string[5] { "ZDO: awaiting guid=", null, null, null, null }; Guid guid2 = guid; obj[1] = guid2.ToString(); obj[2] = " near="; Vector3 val = position; obj[3] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } _interestGuid = guid; _interestPosition = position; _interestUntil = Time.unscaledTime + 2f; } internal unsafe static void Request(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0077: Unknown result type (might be due to invalid IL or missing references) if (!(id == ZDOID.None) && ZDOMan.instance != null && ZRoutedRpc.instance != null && GetConfirmedTarget(id) == null && (!Requests.TryGetValue(id, out var value) || !(Time.unscaledTime - value < 0.5f))) { Requests[id] = Time.unscaledTime; if (TrackedRequests.Add(id)) { ZDO target = GetTarget(id); string[] obj = new string[5] { "ZDO: request zdo=", null, null, null, null }; ZDOID val = id; obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " local="; obj[3] = ((target == null) ? "missing" : "available"); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } ZDOMan.instance.RequestZDO(id); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class PortalCost { internal const float CostMultiplier = 2f; [HarmonyPostfix] private static void OnSceneReady() { PortalConnection.Reset(); Apply(); } internal static void Apply() { ZNetScene instance = ZNetScene.instance; GameObject obj = ((instance != null) ? instance.GetPrefab("portal_wood") : null); Piece val = ((obj != null) ? obj.GetComponent<Piece>() : null); if ((Object)(object)val == (Object)null) { return; } Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { ItemDrop resItem = val2.m_resItem; int num = ((resItem != null) ? ((Object)((Component)resItem).gameObject).name : null) switch { "SurtlingCore" => 2, "GreydwarfEye" => 10, "FineWood" => 20, _ => 0, }; if (num > 0) { val2.m_amount = Mathf.RoundToInt((float)num * 2f); } } } } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] internal static class PortalDestroyedPatch { [HarmonyPrefix] private static void BeforeDestroy(ZDOMan __instance, ZDOID uid) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PortalDirectory.OnDestroyedZDO(__instance, uid); } } internal static class PortalFields { internal const string NameKey = "Landoria.PortalSelector.Name"; internal const string GuidKey = "Landoria.PortalSelector.Guid"; internal const string DestinationGuidKey = "Landoria.PortalSelector.DestinationGuid"; internal const string DestinationPositionKey = "Landoria.PortalSelector.DestinationPosition"; internal const string CreatedAtKey = "Landoria.PortalSelector.CreatedAtUtc"; internal static PortalZdoData Read(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Read(PortalConnection.GetTarget(id)); } internal static PortalZdoData Read(ZDO portal) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00b7: Unknown result type (might be due to invalid IL or missing references) DateTime? createdAtUtc = null; if (portal != null && DateTime.TryParse(portal.GetString("Landoria.PortalSelector.CreatedAtUtc", ""), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result)) { createdAtUtc = result.ToUniversalTime(); } if (portal == null) { return null; } Guid.TryParse(portal.GetString("Landoria.PortalSelector.Guid", ""), out var result2); Guid.TryParse(portal.GetString("Landoria.PortalSelector.DestinationGuid", ""), out var result3); return new PortalZdoData { Name = portal.GetString("Landoria.PortalSelector.Name", ""), Guid = result2, Position = portal.GetPosition(), DestinationGuid = result3, DestinationPosition = portal.GetVec3("Landoria.PortalSelector.DestinationPosition", Vector3.zero), CreatedAtUtc = createdAtUtc }; } internal static bool EnsureIdentity(ZDOID id) { //IL_0000: 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) ZDO target = PortalConnection.GetTarget(id); if (target == null) { return false; } if (Read(target).Guid != Guid.Empty) { return true; } if (!Claim(id)) { return false; } target.Set("Landoria.PortalSelector.Guid", Guid.NewGuid().ToString("D")); SetCreatedAt(target); ZDOMan.instance.SetDirtyPortals(); return true; } private static bool SetCreatedAt(ZDO portal) { if (portal == null || !portal.IsOwner()) { return false; } if (!Read(portal).CreatedAtUtc.HasValue) { portal.Set("Landoria.PortalSelector.CreatedAtUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)); ZDOMan.instance.SetDirtyPortals(); } return true; } internal static bool Claim(ZDOID id) { //IL_0000: 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) ZDO target = PortalConnection.GetTarget(id); if (target == null) { return false; } if (!target.IsOwner()) { ZNetScene instance = ZNetScene.instance; if (instance != null) { GameObject obj = instance.FindInstance(id); if (obj != null) { ZNetView component = obj.GetComponent<ZNetView>(); if (component != null) { component.ClaimOwnership(); } } } } return target.IsOwner(); } internal static bool SetName(ZDOID id, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) ZDO target = PortalConnection.GetTarget(id); if (target == null || !target.IsOwner() || !SetCreatedAt(target)) { return false; } target.Set("Landoria.PortalSelector.Name", name); ZDOMan.instance.SetDirtyPortals(); return true; } internal static bool SetDestination(ZDOID id, Guid destination, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) ZDO target = PortalConnection.GetTarget(id); if (target == null || !target.IsOwner() || !SetCreatedAt(target)) { return false; } target.Set("Landoria.PortalSelector.DestinationGuid", (destination == Guid.Empty) ? "" : destination.ToString("D")); target.Set("Landoria.PortalSelector.DestinationPosition", position); ZDOMan.instance.SetDirtyPortals(); return true; } } [HarmonyPatch(typeof(ZNet), "SendServerSyncPlayerData")] internal static class PortalInterestPatch { [HarmonyPrefix] private static void BeforeSync(ref Vector3 ___m_referencePosition, out Vector3 __state) { //IL_0002: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) __state = ___m_referencePosition; if (PortalConnection.TryGetInterest(out var position)) { PortalConnection.MarkInterestSent(); ___m_referencePosition = position; } else if (PortalDirectory.TryGetStartupInterest(out position)) { PortalDirectory.MarkStartupInterestSent(); ___m_referencePosition = position; } } [HarmonyPostfix] private static void AfterSync(ref Vector3 ___m_referencePosition, Vector3 __state) { //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) ___m_referencePosition = __state; } } internal static class PortalPeerSync { private sealed class PortalNotice { internal readonly long World; internal readonly int Kind; internal readonly ZDOID Id; internal readonly Guid Guid; internal readonly string Name; internal readonly Vector3 Position; internal PortalNotice(long world, int kind, ZDOID id, Guid guid, string name, Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) World = world; Kind = kind; Id = id; Guid = guid; Name = name; Position = position; } } private const string RpcName = "Landoria.PortalSelector.PortalNoticeV2"; private const int Format = 2; private const int Upsert = 1; private const int Remove = 2; private const int MaxPending = 256; private static readonly Queue<PortalNotice> Pending = new Queue<PortalNotice>(); private static ZRoutedRpc _registered; private static bool _sending; private const string SnapshotRequestRpc = "Landoria.PortalSelector.SnapshotRequestV1"; private const string SnapshotReplyRpc = "Landoria.PortalSelector.SnapshotReplyV1"; private const int SnapshotFormat = 1; private const int SnapshotBatchSize = 48; internal static void Update() { EnsureRegistered(); if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && WorldGenerator.instance != null) { while (Pending.Count > 0) { Apply(Pending.Dequeue()); } } } internal static void Reset() { Pending.Clear(); } internal static void AnnouncePortal(ZDOID id, PortalRecord record) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) if (record != null && record.Guid != Guid.Empty && id != ZDOID.None) { Publish(1, id, record.Guid, record.LastKnownName, record.Position); } } internal static void AnnounceRemoval(Guid guid) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (guid != Guid.Empty) { Publish(2, ZDOID.None, guid, "", Vector3.zero); } } private static void EnsureRegistered() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && instance != _registered) { instance.Register<ZPackage>("Landoria.PortalSelector.PortalNoticeV2", (Action<long, ZPackage>)Receive); instance.Register<ZPackage>("Landoria.PortalSelector.SnapshotRequestV1", (Action<long, ZPackage>)ReceiveSnapshotRequest); instance.Register<ZPackage>("Landoria.PortalSelector.SnapshotReplyV1", (Action<long, ZPackage>)ReceiveSnapshotReply); _registered = instance; Pending.Clear(); } } private static void Publish(int kind, ZDOID id, Guid guid, string name, Vector3 position) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) EnsureRegistered(); if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && _registered == ZRoutedRpc.instance) { ZPackage val = new ZPackage(); val.Write(2); val.Write(ZNet.instance.GetWorldUID()); val.Write(kind); val.Write(id); val.Write(guid.ToString("D")); val.Write(name ?? ""); val.Write(position); _sending = true; try { _registered.InvokeRoutedRPC(0L, "Landoria.PortalSelector.PortalNoticeV2", new object[1] { val }); } finally { _sending = false; } string[] obj = new string[5] { "Peer: announced ", kind.ToString(), " guid=", null, null }; Guid guid2 = guid; obj[3] = guid2.ToString(); obj[4] = "."; Plugin.DebugLog(string.Concat(obj)); } } private static void Receive(long sender, ZPackage data) { if (_sending || data == null || data.GetArray().Length > 512) { return; } try { PortalNotice portalNotice = Read(data); if (portalNotice == null) { return; } if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || WorldGenerator.instance == null) { if (Pending.Count < 256) { Pending.Enqueue(portalNotice); } } else { Apply(portalNotice); } } catch (Exception ex) { Plugin.WarningLog("Peer: invalid portal notice (" + ex.GetType().Name + ")."); } } private static PortalNotice Read(ZPackage data) { //IL_001a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (data.ReadInt() != 2) { return null; } long world = data.ReadLong(); int num = data.ReadInt(); ZDOID val = data.ReadZDOID(); string input = data.ReadString(); string text = data.ReadString(); Vector3 val2 = data.ReadVector3(); if ((num != 1 && num != 2) || (num == 1 && val == ZDOID.None) || !Guid.TryParse(input, out var result) || result == Guid.Empty || text.Length > 50 || !Finite(val2.x) || !Finite(val2.y) || !Finite(val2.z)) { return null; } return new PortalNotice(world, num, val, result, text, val2); } private static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static void Apply(PortalNotice notice) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && ZNet.instance.GetWorldUID() == notice.World) { if (notice.Kind == 2) { PortalDirectory.OnPeerRemoval(notice.Guid); } else { PortalDirectory.OnPeerPortal(notice.Id, notice.Guid, notice.Name, notice.Position); } } } internal static void RequestSnapshot() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown EnsureRegistered(); if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && _registered == ZRoutedRpc.instance) { ZPackage val = new ZPackage(); val.Write(1); val.Write(ZNet.instance.GetWorldUID()); Plugin.DebugLog("Peer: join snapshot exchange started."); _sending = true; try { _registered.InvokeRoutedRPC(0L, "Landoria.PortalSelector.SnapshotRequestV1", new object[1] { val }); SendSnapshot(0L); } finally { _sending = false; } Plugin.DebugLog("Peer: exchanged portal snapshots."); } } private static void ReceiveSnapshotRequest(long sender, ZPackage data) { if (_sending || sender == 0L || data == null || data.GetArray().Length > 32 || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } try { if (data.ReadInt() == 1 && data.ReadLong() == ZNet.instance.GetWorldUID()) { Plugin.DebugLog("Peer: snapshot requested by peer=" + sender + "."); SendSnapshot(sender); } } catch (Exception ex) { Plugin.WarningLog("Peer: invalid snapshot request (" + ex.GetType().Name + ")."); } } private static void SendSnapshot(long recipient) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) List<PortalRecord> list = PortalDirectory.KnownRecords(); for (int i = 0; i < list.Count; i += 48) { int num = Math.Min(48, list.Count - i); ZPackage val = new ZPackage(); val.Write(1); val.Write(ZNet.instance.GetWorldUID()); val.Write(num); for (int j = i; j < i + num; j++) { val.Write(list[j].Guid.ToString("D")); val.Write(list[j].Position); } _registered.InvokeRoutedRPC(recipient, "Landoria.PortalSelector.SnapshotReplyV1", new object[1] { val }); Plugin.DebugLog("Peer: sent snapshot batch peer=" + recipient + " offset=" + i + " count=" + num + "."); } Plugin.DebugLog("Peer: shared catalog peer=" + recipient + " total=" + list.Count + "."); } private static void ReceiveSnapshotReply(long sender, ZPackage data) { if (_sending || sender == 0L || data == null || data.GetArray().Length > 8192 || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } try { if (data.ReadInt() == 1 && data.ReadLong() == ZNet.instance.GetWorldUID()) { int num = data.ReadInt(); if (num >= 0 && num <= 48) { Plugin.DebugLog("Peer: received snapshot batch peer=" + sender + " count=" + num + "."); QueueSnapshotEntries(data, num); } } } catch (Exception ex) { Plugin.WarningLog("Peer: invalid snapshot reply (" + ex.GetType().Name + ")."); } } private static void QueueSnapshotEntries(ZPackage data, int count) { //IL_000b: 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_0027: 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_0041: 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) for (int i = 0; i < count; i++) { string input = data.ReadString(); Vector3 val = data.ReadVector3(); if (Guid.TryParse(input, out var result) && result != Guid.Empty && Finite(val.x) && Finite(val.y) && Finite(val.z)) { PortalDirectory.QueueStartupCandidate(result, val); } else { Plugin.DebugLog("Peer: ignored invalid snapshot entry=" + i + "."); } } } } internal sealed class PortalZdoData { internal string Name; internal Guid Guid; internal Vector3 Position; internal Guid DestinationGuid; internal Vector3 DestinationPosition; internal DateTime? CreatedAtUtc; } [HarmonyPatch] internal static class PortalCameraScrollPatch { private static bool _readingCameraScroll; [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPrefix] private static void BeforeCamera() { _readingCameraScroll = PortalDialog.IsOpen; } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPostfix] private static void AfterCamera() { _readingCameraScroll = false; } [HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")] [HarmonyPrefix] private static bool CameraWheel(ref float __result) { if (!_readingCameraScroll) { return true; } __result = 0f; return false; } } [HarmonyPatch] internal static class PortalDialog { [CompilerGenerated] private static class <>O { public static UnityAction <0>__ToggleMenu; public static UnityAction <1>__HideMenu; } private static TextInput _owner; private static GameObject _originalPanel; private static TMP_Text _originalTopic; private static GuiInputField _originalInput; private static GameObject _panel; private static TMP_Text _topic; private static GuiInputField _input; private static Button _choiceButton; private static GameObject _menu; private static GameObject _menuBlocker; private static ZDOID _origin; private static Guid _originGuid; private static Guid _selected; private static List<PortalRecord> _options; private const float PickerHeightIncrease = 16f; private const float ExtraDialogHeight = 32f; private const float TitleSpacing = 2f; private const float ActionSpacing = 12f; private const float MenuHeight = 260f; private const float RowHeight = 36f; private const float ScrollbarWidth = 18f; internal static bool IsOpen { get { if ((Object)(object)_owner != (Object)null && (Object)(object)_panel != (Object)null && (Object)(object)_owner.m_panel == (Object)(object)_panel) { return _panel.activeInHierarchy; } return false; } } internal static void Open(ZDOID origin, List<PortalRecord> records) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) PortalRecord source = PortalDirectory.Find(origin); if ((Object)(object)TextInput.instance == (Object)null || source == null || !records.Any((PortalRecord r) => r.Guid == source.Guid && Available(r))) { return; } _origin = origin; _originGuid = source.Guid; _options = (from r in records where r.Guid != source.Guid && Available(r) orderby BiomeOrder(r.Biome), r.Position.x * r.Position.x + r.Position.z * r.Position.z select r).ThenBy<PortalRecord, string>((PortalRecord r) => PortalDisplay.Name(r.Guid), StringComparer.CurrentCultureIgnoreCase).ToList(); _selected = PlayerDestinations.Get(origin); if (_options.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No known destinations yet.", 0, (Sprite)null, false); } } else { TextInput.instance.RequestText((TextReceiver)(object)new PortalSelectionReceiver(), "Choose destination", 0); RefreshChoice(); } } private unsafe static int BiomeOrder(Biome biome) { return ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() switch { "Meadows" => 0, "BlackForest" => 1, "Swamp" => 2, "Mountain" => 3, "Plains" => 4, "Mistlands" => 5, "AshLands" => 6, "DeepNorth" => 7, "Ocean" => 8, _ => 9, }; } internal static void Confirm() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!(_selected != Guid.Empty) || _options == null || !_options.Exists((PortalRecord record) => record.Guid == _selected && Available(record))) { return; } if (PlayerDestinations.Set(_origin, _selected)) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Portal destination selected.", 0, (Sprite)null, false); } } else { Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, "Could not save the portal destination.", 0, (Sprite)null, false); } } } internal static void OnPortalRemoved(Guid guid) { if (_originGuid == guid && IsOpen) { HideMenu(); _owner.Hide(); } else { if (_options == null || _options.RemoveAll((PortalRecord record) => record.Guid == guid) == 0) { return; } if (_selected == guid) { _selected = Guid.Empty; } RefreshChoice(); if (IsOpen && (Object)(object)_menu != (Object)null && _menu.activeSelf) { if (_options.Count == 0) { HideMenu(); } else { PopulateMenu(); } } } } internal static void OnPortalUpdated(PortalRecord record) { if (!IsOpen || _options == null || record.Guid == _originGuid) { return; } _options.RemoveAll((PortalRecord option) => option.Guid == record.Guid); if (!string.IsNullOrWhiteSpace(record.LastKnownName)) { _options.Add(record); } _options = (from option in _options orderby BiomeOrder(option.Biome), option.Position.x * option.Position.x + option.Position.z * option.Position.z select option).ThenBy<PortalRecord, string>((PortalRecord option) => PortalDisplay.Name(option.Guid), StringComparer.CurrentCultureIgnoreCase).ToList(); RefreshChoice(); if ((Object)(object)_menu != (Object)null && _menu.activeSelf) { if (_options.Count == 0) { HideMenu(); } else { PopulateMenu(); } } } private static bool Available(PortalRecord option) { return PortalDirectory.Find(option.Guid) != null; } internal static void Close() { if ((Object)(object)_owner != (Object)null && (Object)(object)_originalPanel != (Object)null) { _owner.m_panel = _originalPanel; _owner.m_topic = _originalTopic; _owner.m_inputField = _originalInput; } if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); } _panel = null; _menu = null; _menuBlocker = null; _owner = null; } [HarmonyPatch(typeof(TextInput), "RequestText")] [HarmonyPrefix] [HarmonyAfter(new string[] { "Landoria.NearbyStorage" })] private static void BeforeRequest(TextInput __instance, TextReceiver sign) { bool flag = sign is PortalSelectionReceiver; if (!flag && ((Object)(object)_owner != (Object)(object)__instance || (Object)(object)__instance.m_panel != (Object)(object)_panel)) { return; } if (flag && (Object)(object)_owner != (Object)(object)__instance) { Reset(__instance); } if (flag && (Object)(object)_panel == (Object)null) { Create(); } if (!((Object)(object)_panel == (Object)null)) { if (__instance.m_panel.activeSelf) { __instance.Hide(); } __instance.m_panel = (flag ? _panel : _originalPanel); __instance.m_topic = (flag ? _topic : _originalTopic); __instance.m_inputField = (flag ? _input : _originalInput); if (flag) { HideMenu(); } } } private static void Reset(TextInput owner) { Close(); _owner = owner; _originalPanel = owner.m_panel; _originalTopic = owner.m_topic; _originalInput = owner.m_inputField; } private static void Create() { if (!((Object)(object)_originalPanel == (Object)null) && !((Object)(object)_originalTopic == (Object)null) && !((Object)(object)_originalInput == (Object)null)) { _panel = Object.Instantiate<GameObject>(_originalPanel, _originalPanel.transform.parent); ((Object)_panel).name = "PortalSelectorDialog"; _panel.SetActive(false); Transform obj = CopyControl(_originalTopic.transform); _topic = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); Transform obj2 = CopyControl(((Component)_originalInput).transform); _input = ((obj2 != null) ? ((Component)obj2).GetComponent<GuiInputField>() : null); if ((Object)(object)_topic == (Object)null || (Object)(object)_input == (Object)null) { Object.Destroy((Object)(object)_panel); _panel = null; } else { SpaceDialogVertically(); CreatePicker(); } } } private static void SpaceDialogVertically() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) Transform transform = _panel.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; val.SetSizeWithCurrentAnchors((Axis)1, ((Rect)(ref rect)).height + 32f); Transform transform2 = _topic.transform; transform2.position += ((Transform)val).TransformVector(new Vector3(0f, 2f, 0f)); Button[] componentsInChildren = ((Component)val).GetComponentsInChildren<Button>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Transform transform3 = ((Component)componentsInChildren[i]).transform; transform3.position += ((Transform)val).TransformVector(new Vector3(0f, -12f, 0f)); } } } private static Transform CopyControl(Transform source) { string text = ((Object)source).name; Transform parent = source.parent; while ((Object)(object)parent != (Object)(object)_originalPanel.transform) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return _panel.transform.Find(text); } private static void CreatePicker() { //IL_005a: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown Transform transform = ((Component)_input).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); Button componentInChildren = _panel.GetComponentInChildren<Button>(true); if (!((Object)(object)val == (Object)null) && !((Object)(object)componentInChildren == (Object)null)) { GameObject obj = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, ((Transform)val).parent, false); ((Object)obj).name = "DestinationPicker"; Transform transform2 = obj.transform; RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); val2.anchorMin = val.anchorMin; val2.anchorMax = val.anchorMax; val2.offsetMin = val.offsetMin - new Vector2(0f, 8f); val2.offsetMax = val.offsetMax + new Vector2(0f, 8f); _choiceButton = obj.GetComponent<Button>(); _choiceButton.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = _choiceButton.onClick; object obj2 = <>O.<0>__ToggleMenu; if (obj2 == null) { UnityAction val3 = ToggleMenu; <>O.<0>__ToggleMenu = val3; obj2 = (object)val3; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); obj.SetActive(true); ((Component)_input).gameObject.SetActive(false); CreateMenu(val2); } } private static void RefreshChoice() { if (!((Object)(object)_choiceButton == (Object)null)) { PortalRecord portalRecord = _options?.Find((PortalRecord item) => item.Guid == _selected && Available(item)); string text = ((portalRecord == null) ? "Select a portal" : ChoiceLabel(portalRecord)); TMP_Text[] componentsInChildren = ((Component)_choiceButton).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text obj in componentsInChildren) { obj.text = text; obj.enableAutoSizing = true; obj.fontSize = 20f; obj.fontSizeMin = 16f; obj.fontSizeMax = 20f; } } } private static void ToggleMenu() { if ((Object)(object)_menu == (Object)null) { return; } bool flag = !_menu.activeSelf; if (flag) { _options.RemoveAll((PortalRecord record) => !Available(record)); if (_options.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No known destinations available.", 0, (Sprite)null, false); } return; } PopulateMenu(); _menu.transform.SetAsLastSibling(); } _menuBlocker.SetActive(flag); _menu.SetActive(flag); } private static void HideMenu() { if ((Object)(object)_menu != (Object)null) { _menu.SetActive(false); } if ((Object)(object)_menuBlocker != (Object)null) { _menuBlocker.SetActive(false); } } private static void CreateBlocker(RectTransform panel) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0080: 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_008b: Expected O, but got Unknown RectTransform obj = Rect("Destination click blocker", (Transform)(object)panel, new Vector2(10000f, 10000f)); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj.anchorMax = val; obj.anchorMin = val; obj.anchoredPosition = Vector2.zero; ((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = Color.clear; Button obj2 = ((Component)obj).gameObject.AddComponent<Button>(); ((Selectable)obj2).transition = (Transition)0; ButtonClickedEvent onClick = obj2.onClick; object obj3 = <>O.<1>__HideMenu; if (obj3 == null) { UnityAction val2 = HideMenu; <>O.<1>__HideMenu = val2; obj3 = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj3); _menuBlocker = ((Component)obj).gameObject; _menuBlocker.SetActive(false); } private static void CreateMenu(RectTransform button) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0035: 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_0046: 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_0058: 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_0080: 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_009f: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_0100: 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) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) Transform transform = _panel.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); CreateBlocker(val); Vector3[] array = (Vector3[])(object)new Vector3[4]; button.GetWorldCorners(array); Vector3 val2 = ((Transform)val).InverseTransformPoint(array[0]); Vector3 val3 = ((Transform)val).InverseTransformPoint(array[3]); RectTransform val4 = Rect("Portal destinations", (Transform)(object)val, new Vector2(val3.x - val2.x, 260f)); Vector2 val5 = default(Vector2); ((Vector2)(ref val5))..ctor(0.5f, 0.5f); val4.anchorMax = val5; val4.anchorMin = val5; val4.pivot = new Vector2(0f, 1f); val4.anchoredPosition = new Vector2(val2.x, val2.y); ((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.98f); RectTransform val6 = Rect("Viewport", (Transform)(object)val4, Vector2.zero); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = Vector2.zero; val6.offsetMax = new Vector2(-18f, 0f); ((Component)val6).gameObject.AddComponent<RectMask2D>(); RectTransform val7 = Rect("Content", (Transform)(object)val6, Vector2.zero); ((Vector2)(ref val5))..ctor(0f, 1f); val7.anchorMax = val5; val7.anchorMin = val5; val7.pivot = new Vector2(0f, 1f); ScrollRect val8 = ((Component)val4).gameObject.AddComponent<ScrollRect>(); val8.viewport = val6; val8.content = val7; val8.horizontal = false; val8.movementType = (MovementType)2; val8.scrollSensitivity = 800f; CreateScrollbar(val4, val8); _menu = ((Component)val4).gameObject; _menu.SetActive(false); } private static void CreateScrollbar(RectTransform root, ScrollRect scroll) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0080: 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_00af: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Rect("Scrollbar", (Transform)(object)root, Vector2.zero); val.anchorMin = new Vector2(1f, 0f); val.anchorMax = Vector2.one; val.offsetMin = new Vector2(-18f, 0f); val.offsetMax = Vector2.zero; RectTransform val2 = Rect("Handle", (Transform)(object)val, Vector2.zero); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; Vector2 offsetMin = (val2.offsetMax = Vector2.zero); val2.offsetMin = offsetMin; Image val3 = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)val3).color = new Color(1f, 0.68f, 0.3f, 0.85f); Scrollbar val4 = ((Component)val).gameObject.AddComponent<Scrollbar>(); val4.handleRect = val2; ((Selectable)val4).targetGraphic = (Graphic)(object)val3; val4.direction = (Direction)2; scroll.verticalScrollbar = val4; } private static void PopulateMenu() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_00c7: Unknown result type (might be due to invalid IL or missing references) Transform obj = _menu.transform.Find("Viewport/Content"); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); Transform transform = _menu.transform; Rect rect = ((RectTransform)((transform is RectTransform) ? transform : null)).rect; float num = ((Rect)(ref rect)).width - 18f; for (int num2 = ((Transform)val).childCount - 1; num2 >= 0; num2--) { Object.Destroy((Object)(object)((Component)((Transform)val).GetChild(num2)).gameObject); } int num3 = 0; Biome? val2 = null; foreach (PortalRecord option in _options) { if