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 XPortalNetworks v2.0.1
plugins/XPortalNetworks.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Configs; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using XPortalNetworks.Extension; using XPortalNetworks.Patches; using XPortalNetworks.RPC; using XPortalNetworks.RPC.Client; using XPortalNetworks.RPC.Server; using XPortalNetworks.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyTitle("XPortalNetworks")] [assembly: AssemblyDescription("Select portal destination from a list of existing portals with custom networks and private portals support. No more tag pairing, and no more portal hubs!")] [assembly: AssemblyCompany("Vapok")] [assembly: AssemblyProduct("XPortalNetworks")] [assembly: AssemblyFileVersion("2.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.1.0")] [module: UnverifiableCode] [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 Mod { public static class Info { public const string GUID = "vapok.mods.xportalnetworks"; public const string HarmonyGUID = "vapok.mods.xportalnetworks.harmony"; public const string Author = "Vapok"; public const string Name = "XPortalNetworks"; public const string GitHubRepo = "Vapok/XPortalNetworks"; public const string Version = "2.0.1"; public const string Description = "Select portal destination from a list of existing portals with custom networks and private portals support. No more tag pairing, and no more portal hubs!"; public const string WebsiteUrl = "https://github.com/Vapok/XPortalNetworks"; public const int NexusId = 3719; public const string BepInExPackVersion = "5.4.2350"; public const string JotunnVersion = "2.30.0"; } } namespace XPortalNetworks { internal static class Environment { internal static bool IsServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } internal static bool IsHeadless => GUIManager.IsHeadless(); internal static bool GameStarted { get; set; } internal static bool ShuttingDown => Game.instance.m_shuttingDown; internal static long ServerPeerId => ZRoutedRpc.instance.GetServerPeerID(); } internal static class CustomNetworks { internal const int MinId = 1; internal const int MaxId = 15; internal const string ConfigFileName = "xportal_networks.json"; private static readonly UTF8Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); private static readonly Dictionary<long, string> ActiveById = new Dictionary<long, string>(); private static readonly Regex NetworkEntryRegex = new Regex("\"id\"\\s*:\\s*(\\d+)\\s*,\\s*\"name\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"", RegexOptions.Compiled | RegexOptions.CultureInvariant); private static FileSystemWatcher _watcher; private static readonly object ReloadGate = new object(); private static readonly object ReloadTimerLock = new object(); private static SynchronizationContext _mainThreadContext; private static Timer _reloadCoalesceTimer; private const int CoalesceDelayMs = 400; internal static event Action ListChanged; internal static void ResetSession() { lock (ActiveById) { ActiveById.Clear(); } } internal static void ServerSetFromParsed(Dictionary<long, string> parsed) { lock (ActiveById) { ActiveById.Clear(); foreach (KeyValuePair<long, string> item in parsed.OrderBy((KeyValuePair<long, string> k) => k.Key)) { ActiveById[item.Key] = item.Value; } } } internal static void ApplyFromServer(ZPackage pkg) { int num = pkg.ReadInt(); lock (ActiveById) { ActiveById.Clear(); for (int i = 0; i < num; i++) { long num2 = pkg.ReadLong(); string value = pkg.ReadString(); if (num2 >= 1 && num2 <= 15 && !string.IsNullOrEmpty(value)) { ActiveById[num2] = value; } } } CustomNetworks.ListChanged?.Invoke(); } internal static ZPackage PackForServer() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown List<KeyValuePair<long, string>> list; lock (ActiveById) { list = ActiveById.OrderBy((KeyValuePair<long, string> k) => k.Key).ToList(); } ZPackage val = new ZPackage(); val.Write(list.Count); foreach (KeyValuePair<long, string> item in list) { val.Write(item.Key); val.Write(item.Value); } return val; } internal static bool IsActiveId(long id) { if (id < 1 || id > 15) { return false; } lock (ActiveById) { return ActiveById.ContainsKey(id); } } internal static bool TryGetDisplayName(long id, out string displayName) { lock (ActiveById) { return ActiveById.TryGetValue(id, out displayName); } } internal static List<long> GetSortedActiveIds() { lock (ActiveById) { return ActiveById.Keys.OrderBy((long k) => k).ToList(); } } internal static bool IsReservedIdRange(long id) { if (id >= 1) { return id <= 15; } return false; } internal static void MigrateInvalidNetworks() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (!Environment.IsServer) { return; } foreach (KnownPortal item in KnownPortalsManager.Instance.GetList().ToList()) { if (IsReservedIdRange(item.NetworkOwnerPlayerId) && !IsActiveId(item.NetworkOwnerPlayerId)) { item.NetworkOwnerPlayerId = 0L; item.NetworkOwnerDisplayName = string.Empty; KnownPortalsManager.Instance.AddOrUpdate(item); ZdoTools.UpdateFromKnownPortal(delayed: false, item); SendToClient.SyncPortal(item); Log.Info($"Migrated portal `{item.Id}` to Global network (network id was removed or invalid)."); } } } internal static void NotifyListChangedLocal() { CustomNetworks.ListChanged?.Invoke(); } internal static void InitializeServer() { if (!Environment.IsServer) { return; } _mainThreadContext = SynchronizationContext.Current; EnsureDefaultConfigExists(); ReloadFromDiskAndBroadcast(isInitial: true); string directoryName = Path.GetDirectoryName(GetConfigFilePath()); if (string.IsNullOrEmpty(directoryName) || !Directory.Exists(directoryName)) { return; } try { _watcher?.Dispose(); _watcher = new FileSystemWatcher(directoryName) { Filter = "xportal_networks.json", NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; _watcher.Changed += OnWatcherEvent; _watcher.Created += OnWatcherEvent; _watcher.Renamed += OnWatcherRenamed; _watcher.EnableRaisingEvents = true; Log.Debug("Watching `" + directoryName + "` for `xportal_networks.json` changes."); } catch (Exception ex) { Log.Error("Could not watch custom networks config folder: " + ex.Message); } } internal static void ShutdownServer() { lock (ReloadTimerLock) { _reloadCoalesceTimer?.Dispose(); _reloadCoalesceTimer = null; } _watcher?.Dispose(); _watcher = null; } private static string GetConfigFilePath() { return Path.Combine(Paths.ConfigPath, "XPortalNetworks", "xportal_networks.json"); } private static string ReadEmbeddedTemplate() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.EndsWith("xportal_networks.json", StringComparison.OrdinalIgnoreCase)) { continue; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { continue; } using StreamReader streamReader = new StreamReader(stream, Utf8NoBom); return streamReader.ReadToEnd(); } } catch (Exception ex) { Log.Error("Failed to read embedded `xportal_networks.json` from assembly: " + ex.GetType().Name + ": " + ex.Message); } return null; } private static void EnsureDefaultConfigExists() { string configFilePath = GetConfigFilePath(); try { string directoryName = Path.GetDirectoryName(configFilePath); if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } if (!File.Exists(configFilePath)) { string text = ReadEmbeddedTemplate(); if (!string.IsNullOrEmpty(text)) { File.WriteAllText(configFilePath, text, Utf8NoBom); Log.Info("Created `" + configFilePath + "` from embedded `xportal_networks.json`."); } else { Log.Error("Embedded default template `xportal_networks.json` not found; cannot create `" + configFilePath + "`."); } } } catch (Exception ex) { Log.Error("Could not create default custom networks file: " + ex.Message); } } private static bool TryReadConfigFile(out string text, out bool readError) { text = null; readError = false; string configFilePath = GetConfigFilePath(); try { if (!File.Exists(configFilePath)) { return false; } text = File.ReadAllText(configFilePath, Utf8NoBom); return true; } catch (Exception ex) { readError = File.Exists(configFilePath); Log.Error("Could not read custom networks file `" + configFilePath + "`: " + ex.GetType().Name + ": " + ex.Message); return false; } } private static Dictionary<long, string> ParseConfigJson(string raw) { Dictionary<long, string> dictionary = new Dictionary<long, string>(); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } raw = StripUtf8Bom(raw.Trim()); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; try { foreach (Match item in NetworkEntryRegex.Matches(raw)) { if (!int.TryParse(item.Groups[1].Value, out var result) || result < 1 || result > 15) { num++; continue; } string text; try { text = UnescapeJsonString(item.Groups[2].Value); } catch (Exception ex) { num4++; Log.Warning($"Custom networks JSON: skipped entry for id {result} (invalid escape sequence in name): {ex.GetType().Name}: {ex.Message}"); continue; } if (string.IsNullOrWhiteSpace(text)) { num2++; continue; } text = PortalNetwork.SanitizeNetworkOwnerDisplayName(text); if (string.IsNullOrEmpty(text)) { num2++; continue; } long key = result; if (dictionary.ContainsKey(key)) { num3++; } else { dictionary.Add(key, text); } } } catch (Exception ex2) { Log.Error("Custom networks JSON: unexpected failure while scanning `xportal_networks.json`: " + ex2.GetType().Name + ": " + ex2.Message); return dictionary; } if (num > 0) { Log.Warning(string.Format("Custom networks JSON: skipped {0} {1} with id outside {2}–{3}.", num, (num == 1) ? "entry" : "entries", 1, 15)); } if (num2 > 0) { Log.Warning(string.Format("Custom networks JSON: skipped {0} {1} with empty or invalid name after sanitization.", num2, (num2 == 1) ? "entry" : "entries")); } if (num3 > 0) { Log.Warning(string.Format("Custom networks JSON: skipped {0} duplicate id {1}.", num3, (num3 == 1) ? "entry" : "entries")); } if (dictionary.Count == 0 && raw.Length > 2) { Log.Warning(string.Format("Custom networks JSON: no valid entries found in `{0}`. Expected patterns like \"id\": 1, \"name\": \"...\" with ids in {1}–{2}. Check the file format.", "xportal_networks.json", 1, 15)); } return dictionary; } private static string StripUtf8Bom(string s) { if (string.IsNullOrEmpty(s) || s[0] != '\ufeff') { return s; } return s.Substring(1); } private static string UnescapeJsonString(string s) { if (string.IsNullOrEmpty(s) || s.IndexOf('\\') < 0) { return s; } try { StringBuilder stringBuilder = new StringBuilder(s.Length); for (int i = 0; i < s.Length; i++) { if (s[i] != '\\' || i + 1 >= s.Length) { stringBuilder.Append(s[i]); continue; } i++; switch (s[i]) { case '"': stringBuilder.Append('"'); break; case '\\': stringBuilder.Append('\\'); break; case '/': stringBuilder.Append('/'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'n': stringBuilder.Append('\n'); break; case 'r': stringBuilder.Append('\r'); break; case 't': stringBuilder.Append('\t'); break; case 'u': { if (i + 4 < s.Length && uint.TryParse(s.Substring(i + 1, 4), NumberStyles.HexNumber, null, out var result)) { stringBuilder.Append((char)result); i += 4; } else { stringBuilder.Append('u'); } break; } default: stringBuilder.Append(s[i]); break; } } return stringBuilder.ToString(); } catch (Exception innerException) { throw new InvalidOperationException("Failed to unescape JSON string fragment.", innerException); } } private static bool IsOurConfigFile(string name) { if (string.IsNullOrEmpty(name)) { return false; } return name.Equals("xportal_networks.json", StringComparison.OrdinalIgnoreCase); } private static void OnWatcherRenamed(object sender, RenamedEventArgs e) { if (IsOurConfigFile(e.Name)) { QueueReload(); } } private static void OnWatcherEvent(object sender, FileSystemEventArgs e) { if (IsOurConfigFile(e.Name)) { QueueReload(); } } private static void QueueReload() { lock (ReloadTimerLock) { _reloadCoalesceTimer?.Dispose(); _reloadCoalesceTimer = new Timer(delegate { OnCoalesceTimerFired(); }, null, 400, -1); } } private static void OnCoalesceTimerFired() { try { SynchronizationContext mainThreadContext = _mainThreadContext; if (mainThreadContext != null) { mainThreadContext.Post(delegate { try { ReloadFromDiskAndBroadcast(isInitial: false); } catch (Exception ex2) { Log.Error("Custom networks reload failed: " + ex2.Message); } }, null); } else { Log.Warning("No synchronization context; reloading custom networks on the watcher thread (may be unsafe)."); ReloadFromDiskAndBroadcast(isInitial: false); } } catch (Exception ex) { Log.Error("Custom networks reload scheduling failed: " + ex.Message); } } private static void ReloadFromDiskAndBroadcast(bool isInitial) { lock (ReloadGate) { if (!TryReadConfigFile(out var text, out var readError)) { if (!readError) { EnsureDefaultConfigExists(); } if (!TryReadConfigFile(out text, out readError) || text == null) { if (readError) { Log.Error("Keeping the previous custom network list; fix `" + GetConfigFilePath() + "` and save, or restart the server after correcting the file."); return; } text = string.Empty; } } ServerSetFromParsed(ParseConfigJson(text ?? string.Empty)); MigrateInvalidNetworks(); if (!isInitial) { SendToClient.BroadcastCustomNetworks(PackForServer()); } if (!isInitial) { Log.Info("Custom networks file reloaded and pushed to clients."); } if (!Environment.IsHeadless) { NotifyListChangedLocal(); } } } } internal sealed class KnownPortalsManager : IDisposable { private static readonly Lazy<KnownPortalsManager> lazy = new Lazy<KnownPortalsManager>(() => new KnownPortalsManager()); private readonly Dictionary<ZDOID, KnownPortal> knownPortals = new Dictionary<ZDOID, KnownPortal>(); public static KnownPortalsManager Instance => lazy.Value; public int Count => knownPortals.Count; private KnownPortalsManager() { } public bool ContainsId(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return knownPortals.ContainsKey(id); } public KnownPortal GetKnownPortalById(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return knownPortals[id]; } public bool TryGetValue(ZDOID id, out KnownPortal portal) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return knownPortals.TryGetValue(id, out portal); } public KnownPortal GetKnownPortalByPreviousId(ZDOID previousId) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from kvp in knownPortals where kvp.Value.PreviousId == previousId select kvp.Value).FirstOrDefault(); } public string GetNetworkOwnerDisplayNameForPlayerId(long networkOwnerPlayerId) { if (networkOwnerPlayerId == 0L) { return null; } foreach (KnownPortal value in knownPortals.Values) { if (value.NetworkOwnerPlayerId == networkOwnerPlayerId && !string.IsNullOrEmpty(value.NetworkOwnerDisplayName)) { return value.NetworkOwnerDisplayName; } } return null; } public List<KnownPortal> GetList() { return knownPortals.Values.ToList(); } public ZPackage Pack() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown List<KnownPortal> list = GetList(); ZPackage val = new ZPackage(); val.Write(list.Count); foreach (KnownPortal item in list) { val.Write(item.Pack()); } return val; } public List<KnownPortal> GetSortedList() { List<KnownPortal> list = GetList(); list.Sort((KnownPortal valueA, KnownPortal valueB) => valueA.Name.CompareTo(valueB.Name)); return list; } public List<KnownPortal> GetPortalsWithTarget(ZDOID target) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return knownPortals.Values.Where((KnownPortal p) => p.Target == target).ToList(); } public KnownPortal AddOrUpdate(KnownPortal portal) { //IL_0002: 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_0015: 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) if (!ContainsId(portal.Id)) { knownPortals.Add(portal.Id, portal); } else { knownPortals[portal.Id] = portal; } return knownPortals[portal.Id]; } public bool Remove(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return knownPortals.Remove(id); } public bool Remove(KnownPortal portal) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Remove(portal.Id); } public void UpdateFromZDOList(List<ZDO> zdoList) { //IL_001b: 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_004e: 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) List<KnownPortal> list = new List<KnownPortal>(); foreach (ZDO zdo in zdoList) { KnownPortal item = new KnownPortal(zdo.m_uid) { Name = zdo.GetString("tag", ""), Location = zdo.GetPosition(), PreviousId = zdo.GetZDOID("XPortalNetworks_PreviousId"), Target = zdo.GetZDOID("XPortalNetworks_TargetId"), NetworkOwnerPlayerId = ZdoTools.GetNetworkOwnerPlayerId(zdo), NetworkOwnerDisplayName = ZdoTools.GetNetworkOwnerDisplayName(zdo), IsPrivate = ZdoTools.GetIsPrivate(zdo) }; list.Add(item); } UpdateFromList(list); } public void UpdateFromResyncPackage(ZPackage pkg) { int num = pkg.ReadInt(); Log.Debug($"Received {num} portals from server"); List<KnownPortal> list = new List<KnownPortal>(); if (num > 0) { for (int i = 0; i < num; i++) { KnownPortal item = new KnownPortal(pkg.ReadPackage()); list.Add(item); } } UpdateFromList(list); } private void UpdateFromList(List<KnownPortal> updatedPortals) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) Log.Debug($"Updating {updatedPortals.Count} portals"); foreach (KnownPortal updatedPortal in updatedPortals) { AddOrUpdate(updatedPortal); } IEnumerable<KnownPortal> enumerable = from p in GetList() where !updatedPortals.Contains(p) select p; Log.Debug($"Removing {enumerable.Count()} portals"); foreach (KnownPortal item in enumerable) { Remove(item); } IEnumerable<KnownPortal> enumerable2 = from p in GetList() where p.Target != ZDOID.None && !ContainsId(p.Target) select p; Log.Debug($"Retargeting {enumerable2.Count()} portals"); foreach (KnownPortal item2 in enumerable2) { item2.Target = ZDOID.None; SendToServer.AddOrUpdateRequest(item2); } Log.Info("Known portals updated"); ReportAllPortals(); } public KnownPortal FindByLocation(Vector3 location) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return knownPortals.Values.Where(delegate(KnownPortal p) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) Vector3 val = p.Location.Round(); return ((Vector3)(ref val)).Equals(location); }).FirstOrDefault(); } public ZDOID FindDefaultPortal() { //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_0019: 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_002c: 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) Vector3 location = XPortalNetworksConfig.Instance.Local.DefaultPortal.Value.Round(); return FindByLocation(location)?.Id ?? ZDOID.None; } public void ReportAllPortals() { if (!knownPortals.Any()) { Log.Debug(" No portals found."); return; } foreach (KnownPortal value in knownPortals.Values) { Log.Debug($" {value}"); } } public void Reset() { knownPortals.Clear(); } public void Dispose() { knownPortals?.Clear(); } } internal static class Log { public static void Debug(object message) { MethodBase? method = new StackTrace().GetFrame(1).GetMethod(); string name = method.DeclaringType.Name; string name2 = method.Name; Logger.LogDebug((object)$"[{name}.{name2}] {message}"); } public static void Info(object message) { Logger.LogInfo(message); } public static void Warning(object message) { Logger.LogWarning(message); } public static void Error(object message) { Logger.LogError(message); } public static void Fatal(object message) { Logger.LogFatal(message); } } internal static class NetPeerUtility { internal static long GetPeerPlayerId(long peerId) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return 0L; } ZNetPeer peer = ZNet.instance.GetPeer(peerId); if (peer == null) { if (ZNet.instance.IsServer() && peerId == ZNet.GetUID()) { if ((Object)(object)Player.m_localPlayer != (Object)null) { return Player.m_localPlayer.GetPlayerID(); } if (!((Object)(object)Game.instance != (Object)null)) { return 0L; } return Game.instance.GetPlayerProfile().GetPlayerID(); } return 0L; } if (((ZDOID)(ref peer.m_characterID)).IsNone()) { return 0L; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { return 0L; } return zDO.GetLong(ZDOVars.s_playerID, 0L); } internal static bool IsPeerPrivilegedForPortalNetwork(long peerId) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } ZNetPeer peer = ZNet.instance.GetPeer(peerId); if (peer == null) { if (ZNet.instance.IsServer() && peerId == ZNet.GetUID()) { return ZNet.instance.LocalPlayerIsAdminOrHost(); } return false; } return ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } } internal static class PortalNetwork { internal const long DestinationNetworkMyPrivateBucket = -1L; internal static string SanitizeNetworkOwnerDisplayName(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return string.Empty; } string text = raw.Trim(); if (text.Length > 64) { text = text.Substring(0, 64); } return text; } internal static string FormatNetworkLabel(long ownerPlayerId) { switch (ownerPlayerId) { case -1L: return Localization.instance.Localize("$hud_xportal_network_my_private"); case 0L: return Localization.instance.Localize("$hud_xportal_network_global"); case 1L: case 2L: case 3L: case 4L: case 5L: case 6L: case 7L: case 8L: case 9L: case 10L: case 11L: case 12L: case 13L: case 14L: case 15L: { if (CustomNetworks.TryGetDisplayName(ownerPlayerId, out var displayName)) { return displayName; } return ownerPlayerId.ToString(); } default: { string text = Localization.instance.Localize("$hud_xportal_network_suffix"); if (IsLocalPlayerNetworkId(ownerPlayerId)) { return ResolvePlayerDisplayName(ownerPlayerId).Trim() + " " + text; } string networkOwnerDisplayNameForPlayerId = KnownPortalsManager.Instance.GetNetworkOwnerDisplayNameForPlayerId(ownerPlayerId); if (!string.IsNullOrEmpty(networkOwnerDisplayNameForPlayerId)) { return networkOwnerDisplayNameForPlayerId.Trim() + " " + text; } string text2 = ResolvePlayerDisplayName(ownerPlayerId).Trim(); if (string.IsNullOrEmpty(text2)) { return text; } return text2 + " " + text; } } } private static bool IsLocalPlayerNetworkId(long ownerPlayerId) { if ((Object)(object)Player.m_localPlayer != (Object)null) { return Player.m_localPlayer.GetPlayerID() == ownerPlayerId; } if ((Object)(object)Game.instance != (Object)null) { return Game.instance.GetPlayerProfile().GetPlayerID() == ownerPlayerId; } return false; } private static string ResolvePlayerDisplayName(long ownerPlayerId) { if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == ownerPlayerId) { return Player.m_localPlayer.GetPlayerName(); } Player player = Player.GetPlayer(ownerPlayerId); if ((Object)(object)player != (Object)null) { string playerName = player.GetPlayerName(); if (!string.IsNullOrWhiteSpace(playerName) && playerName != "...") { return playerName; } } string text = TryResolveByWorldState(ownerPlayerId); if (!string.IsNullOrEmpty(text)) { return text; } if ((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile().GetPlayerID() == ownerPlayerId) { return Game.instance.GetPlayerProfile().GetName(); } return ownerPlayerId.ToString(); } internal static string TryResolveByWorldState(long ownerPlayerId) { //IL_009c: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if (ownerPlayerId == 0L || (Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return null; } foreach (ZDO allCharacterZDO in ZNet.instance.GetAllCharacterZDOS()) { if (allCharacterZDO != null && allCharacterZDO.GetLong(ZDOVars.s_playerID, 0L) == ownerPlayerId) { string text = allCharacterZDO.GetString(ZDOVars.s_playerName, string.Empty); if (IsUsablePlayerName(text)) { return text.Trim(); } } } foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (((ZDOID)(ref characterID)).IsNone()) { continue; } ZDO zDO = ZDOMan.instance.GetZDO(player.m_characterID); if (zDO != null && zDO.GetLong(ZDOVars.s_playerID, 0L) == ownerPlayerId) { if (!string.IsNullOrEmpty(player.m_name)) { return player.m_name.Trim(); } if (!string.IsNullOrEmpty(player.m_userInfo.m_displayName)) { return player.m_userInfo.m_displayName.Trim(); } string text2 = zDO.GetString(ZDOVars.s_playerName, string.Empty); if (IsUsablePlayerName(text2)) { return text2.Trim(); } } } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (!((ZDOID)(ref peer.m_characterID)).IsNone()) { ZDO zDO2 = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO2 != null && zDO2.GetLong(ZDOVars.s_playerID, 0L) == ownerPlayerId && !string.IsNullOrEmpty(peer.m_playerName)) { return peer.m_playerName.Trim(); } } } return null; } private static bool IsUsablePlayerName(string name) { if (string.IsNullOrWhiteSpace(name)) { return false; } if (name == "...") { return false; } return true; } } internal static class PortalColour { private const string DefaultColour = "#FF6400"; private const string DefaultStoneColour = "#33C7FF"; public static string GetPortalColour(ZDOID portalId) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (portalId == ZDOID.None) { return "#FF6400"; } ZDO zDO = ZDOMan.instance.GetZDO(portalId); GameObject prefab = ZNetScene.instance.GetPrefab(zDO.m_prefab); if (!Object.op_Implicit((Object)(object)prefab)) { Log.Debug($"Could not find prefab `{zDO.m_prefab}`"); return "#FF6400"; } if (string.Equals(((Object)prefab).name, "portal", StringComparison.OrdinalIgnoreCase)) { return "#33C7FF"; } Transform val = prefab.transform.Find("_target_found_red/Point light"); if (!Object.op_Implicit((Object)(object)val)) { Log.Debug("Portal prefab `" + ((Object)prefab).name + "` does not have a Point light"); return "#FF6400"; } Light component = ((Component)val).GetComponent<Light>(); if (!Object.op_Implicit((Object)(object)component)) { Log.Debug("Portal prefab `" + ((Object)prefab).name + "` does not have a Light component"); return "#FF6400"; } Color color = component.color; return "#" + ColorUtility.ToHtmlStringRGB(color); } } internal class QueuedAction { private static readonly Dictionary<Guid, QueuedAction> queuedActions; private readonly Action<bool, object> Action; private int Delay; private object State; static QueuedAction() { queuedActions = new Dictionary<Guid, QueuedAction>(); } public static void Update() { if (queuedActions.Count > 0) { Trigger(); Countdown(); Cleanup(); } } public static void Queue(Action<bool, object> action, int delay = 2, object state = null) { QueuedAction value = new QueuedAction(action, delay, state); queuedActions.Add(Guid.NewGuid(), value); } private static void Trigger() { foreach (KeyValuePair<Guid, QueuedAction> item in queuedActions.Where((KeyValuePair<Guid, QueuedAction> kvp) => kvp.Value.Delay == 0).ToList()) { queuedActions.Remove(item.Key); item.Value.Action(arg1: false, item.Value.State); } } private static void Countdown() { foreach (Guid item in queuedActions.Keys.ToList()) { queuedActions[item].Delay--; } } private static void Cleanup() { foreach (KeyValuePair<Guid, QueuedAction> item in queuedActions.Where((KeyValuePair<Guid, QueuedAction> kvp) => kvp.Value.Delay < 0).ToList()) { Log.Debug("Cleaned up stale action " + item.Value.Action.Method.Name); queuedActions.Remove(item.Key); } } private QueuedAction(Action<bool, object> action, int delay, object state = null) { Action = action; Delay = delay; State = state; } } internal sealed class XPortalNetworksConfig { public class ConfigSettings { public bool PingMapDisabled; public bool DisplayPortalColour; public bool DoublePortalCosts; public ConfigEntry<Vector3> DefaultPortal; public ConfigEntry<bool> DefaultPrivatePortal; public bool HidePortalDistance; public bool RestrictPortalRemoval; } private static readonly Lazy<XPortalNetworksConfig> lazy = new Lazy<XPortalNetworksConfig>(() => new XPortalNetworksConfig()); private const string Desc_EnforcedByServer = " This setting is enforced (but not overwritten) by the server."; private ConfigFile configFile; public static XPortalNetworksConfig Instance => lazy.Value; public ConfigSettings Local { get; set; } public ConfigSettings Server { get; set; } public event Action OnLocalConfigChanged; public event Action OnServerConfigChanged; private XPortalNetworksConfig() { Local = new ConfigSettings(); Server = new ConfigSettings(); } public void LoadLocalConfig(ConfigFile configFile) { this.configFile = configFile; ReloadLocalConfig(); this.configFile.ConfigReloaded += LocalConfigChanged; this.configFile.SettingChanged += LocalConfigChanged; if (Environment.IsServer) { Server = Local; } } private void ReloadLocalConfig() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) configFile.Bind<int>("General", "NexusID", 3719, "Nexus mod ID for updates (do not change)"); ConfigEntry<bool> val = configFile.Bind<bool>("General", "PingMapDisabled", false, "Disable the Ping Map button completely. For players who wish to play without a map. This setting is enforced (but not overwritten) by the server."); Local.PingMapDisabled = val.Value; ConfigEntry<bool> val2 = configFile.Bind<bool>("General", "DisplayPortalColour", false, "Show a \">>\" tag in the list of portals that has the same colour as the light that the portal emits (integration with \"Advanced Portals\" by RandyKnapp)."); Local.DisplayPortalColour = val2.Value; ConfigEntry<bool> val3 = configFile.Bind<bool>("General", "DoublePortalCosts", false, "By using XPortalNetworks, you effectively only need half the amount of portals. To compensate for that, we can double the costs of portals. This setting is enforced (but not overwritten) by the server."); Local.DoublePortalCosts = val3.Value; Local.DefaultPortal = configFile.Bind<Vector3>("General", "DefaultPortal", Vector3.zero, "The Portal that newly built Portals immediately connect to."); Local.DefaultPrivatePortal = configFile.Bind<bool>("General", "DefaultPrivatePortal", true, "If true, newly placed portals start as private (owner-only). If false, they start public on the Global network until changed."); ConfigEntry<bool> val4 = configFile.Bind<bool>("General", "HidePortalDistance", false, "In the list of portals, do not show how far away other portals are. This setting is enforced (but not overwritten) by the server."); Local.HidePortalDistance = val4.Value; ConfigEntry<bool> val5 = configFile.Bind<bool>("General", "RestrictPortalRemoval", false, "When true, only the player who placed the portal or a server admin may remove it with the hammer. Other removal (e.g. structural damage) is unchanged. This setting is enforced (but not overwritten) by the server."); Local.RestrictPortalRemoval = val5.Value; } private void LocalConfigChanged(object sender, EventArgs e) { ReloadLocalConfig(); if (Environment.IsServer) { Log.Debug("The config was changed, propagating to clients.."); SendToClient.Config(PackLocalConfig()); } this.OnLocalConfigChanged?.Invoke(); } public ZPackage PackLocalConfig() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0027: 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_004a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(Local.PingMapDisabled); val.Write(Local.DoublePortalCosts); val.Write(Local.HidePortalDistance); val.Write(Local.RestrictPortalRemoval); return val; } public void ReceiveServerConfig(ZPackage pkg) { Server.PingMapDisabled = pkg.ReadBool(); Server.DoublePortalCosts = pkg.ReadBool(); Server.HidePortalDistance = pkg.ReadBool(); try { Server.RestrictPortalRemoval = pkg.ReadBool(); } catch (EndOfStreamException) { Server.RestrictPortalRemoval = false; } Log.Debug($"PingMapDisabled {{ Local: {Local.PingMapDisabled}, Server: {Server.PingMapDisabled} }}"); Log.Debug($"DoublePortalCosts {{ Local: {Local.DoublePortalCosts}, Server: {Server.DoublePortalCosts} }}"); Log.Debug($"HidePortalDistance {{ Local: {Local.HidePortalDistance}, Server: {Server.HidePortalDistance} }}"); Log.Debug($"RestrictPortalRemoval {{ Local: {Local.RestrictPortalRemoval}, Server: {Server.RestrictPortalRemoval} }}"); this.OnServerConfigChanged?.Invoke(); } } public class KnownPortal { public ZDOID Id { get; set; } public string Name { get; set; } public ZDOID PreviousId { get; set; } public ZDOID Target { get; set; } public Vector3 Location { get; set; } public string Colour { get; set; } public long NetworkOwnerPlayerId { get; set; } public string NetworkOwnerDisplayName { get; set; } public bool IsPrivate { get; set; } public bool IsDefaultPortal { get { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Location.Round(); return ((Vector3)(ref val)).Equals(XPortalNetworksConfig.Instance.Local.DefaultPortal.Value.Round()); } } public KnownPortal(ZDOID id) { //IL_0007: 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) //IL_0024: 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_003f: Unknown result type (might be due to invalid IL or missing references) Id = id; Name = string.Empty; Location = Vector3.zero; PreviousId = ZDOID.None; Target = KnownPortalsManager.Instance.FindDefaultPortal(); Colour = PortalColour.GetPortalColour(id); NetworkOwnerPlayerId = 0L; NetworkOwnerDisplayName = string.Empty; IsPrivate = false; } public KnownPortal(ZDOID id, Vector3 location) : this(id) { //IL_0001: 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) Location = location; IsPrivate = XPortalNetworksConfig.Instance.Local.DefaultPrivatePortal.Value; } public KnownPortal(ZPackage pkg) { //IL_0008: 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_002c: 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) Id = pkg.ReadZDOID(); Name = pkg.ReadString(); Location = pkg.ReadVector3(); PreviousId = pkg.ReadZDOID(); Target = pkg.ReadZDOID(); Colour = pkg.ReadString(); NetworkOwnerPlayerId = pkg.ReadLong(); NetworkOwnerDisplayName = ReadOptionalString(pkg); IsPrivate = ReadOptionalBool(pkg); } private static string ReadOptionalString(ZPackage pkg) { try { return pkg.ReadString(); } catch (EndOfStreamException) { return string.Empty; } } private static bool ReadOptionalBool(ZPackage pkg) { try { return pkg.ReadBool(); } catch (EndOfStreamException) { return false; } } public string GetFriendlyName() { string name = Name; if (string.IsNullOrEmpty(name)) { return Localization.instance.Localize("$piece_portal_tag_none"); } return name; } public string GetFriendlyTargetName() { //IL_001e: 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_0030: Unknown result type (might be due to invalid IL or missing references) if (!HasTarget()) { return Localization.instance.Localize("$piece_portal_target_none"); } if (!KnownPortalsManager.Instance.ContainsId(Target)) { return $"{Target} (invalid)"; } return KnownPortalsManager.Instance.GetKnownPortalById(Target).GetFriendlyName(); } public bool HasTarget() { //IL_0001: 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_000d: 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) //IL_001f: Unknown result type (might be due to invalid IL or missing references) _ = Target; if (Target != ZDOID.None) { ZDOID target = Target; return !((ZDOID)(ref target)).IsNone(); } return false; } public ZPackage Pack() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_002b: 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_0037: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(Id); val.Write(Name); val.Write(Location); val.Write(PreviousId); val.Write(Target); val.Write(Colour); val.Write(NetworkOwnerPlayerId); val.Write(NetworkOwnerDisplayName ?? string.Empty); val.Write(IsPrivate); return val; } public bool Targets(ZDOID target) { //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) return Target == target; } public override string ToString() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) return $"{{ Id: `{Id}`, Name; `{GetFriendlyName()}`, Location: `{Location}`, NetworkOwner: `{NetworkOwnerPlayerId}` (`{NetworkOwnerDisplayName}`), Private: `{IsPrivate}`, Target: `{Target}` (`{GetFriendlyTargetName()}`), Colour: `{Colour}` }}"; } public bool IsGlobalNetwork() { return NetworkOwnerPlayerId == 0; } } [BepInPlugin("vapok.mods.xportalnetworks", "XPortalNetworks", "2.0.1")] [BepInIncompatibility("com.sweetgiorni.anyportal")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class XPortalNetworks : BaseUnityPlugin { public const string Key_TargetId = "XPortalNetworks_TargetId"; public const string Key_PreviousId = "XPortalNetworks_PreviousId"; public const string Key_NetworkOwnerPlayerId = "XPortalNetworks_NetworkOwnerPlayerId"; public const string Key_NetworkOwnerDisplayName = "XPortalNetworks_NetworkOwnerDisplayName"; public const string Key_IsPrivate = "XPortalNetworks_IsPrivate"; public const string StonePortalPrefabName = "portal"; private static bool portalRecipeAltered; private static Dictionary<string, int> portalRecipeOriginal; private void Awake() { Log.Debug("I HAVE ARRIVED!"); XPortalNetworksConfig.Instance.LoadLocalConfig(((BaseUnityPlugin)this).Config); XPortalNetworksConfig.Instance.OnLocalConfigChanged += OnLocalConfigChanged; XPortalNetworksConfig.Instance.OnServerConfigChanged += OnServerConfigChanged; CustomNetworks.ListChanged += OnNetworksListChanged; if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance.AddInputs(); } MinimapManager.OnVanillaMapDataLoaded += MinimapManager_OnVanillaMapDataLoaded; Patcher.Patch(); } private void Update() { QueuedAction.Update(); if (!Environment.IsHeadless && Environment.GameStarted && ZInput.instance != null && PortalConfigurationPanel.Instance.IsActive()) { PortalConfigurationPanel.Instance.HandleInput(); PortalConfigurationPanel.Instance.SyncListScroll(); } } private void OnDestroy() { Log.Debug("Full portal list:"); KnownPortalsManager.Instance.ReportAllPortals(); Patcher.Unpatch(); CustomNetworks.ShutdownServer(); if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance?.Dispose(); } KnownPortalsManager.Instance?.Dispose(); } private static void MinimapManager_OnVanillaMapDataLoaded() { SendToServer.ConfigRequest(); SendToServer.RequestCustomNetworks(); long sessionID = ZDOMan.GetSessionID(); string name = Game.instance.GetPlayerProfile().GetName(); SendToServer.SyncRequest($"{name} ({sessionID}) has joined the game"); } private static void UpdatePortalRecipe() { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { Log.Error("ObjectDB not instantiated"); return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer"); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { Log.Error("Could not find Hammer prefab"); return; } Piece val2 = (from go in val.m_itemData.m_shared.m_buildPieces.m_pieces where ((Object)go).name.Equals("portal_wood") select go.GetComponent<Piece>()).FirstOrDefault(); BackUpPortalRecipe(val2.m_resources); Requirement[] resources = val2.m_resources; foreach (Requirement val3 in resources) { string name = ((Object)val3.m_resItem).name; int num2 = portalRecipeOriginal[name]; int num3 = num2; if (XPortalNetworksConfig.Instance.Server.DoublePortalCosts) { num3 = 2 * num2; Log.Debug($"Doubling amount for requirement {((Object)val3.m_resItem).name} for item {((Object)val2).name} from {num2} to {num3}"); } else if (portalRecipeAltered) { Log.Debug($"Resetting amount for requirement {((Object)val3.m_resItem).name} for item {((Object)val2).name} to {num3}"); } val3.m_amount = num3; } portalRecipeAltered = XPortalNetworksConfig.Instance.Server.DoublePortalCosts; } private static void BackUpPortalRecipe(Requirement[] requirements) { if (portalRecipeOriginal == null || portalRecipeOriginal.Count <= 0) { Log.Debug("Copying original requirements for portal recipe"); portalRecipeOriginal = new Dictionary<string, int>(); foreach (Requirement val in requirements) { portalRecipeOriginal.Add(((Object)val.m_resItem).name, val.m_amount); } } } private static void OnNetworksListChanged() { if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance.OnNetworksListChanged(); } } internal static void OnLocalConfigChanged() { } internal static void OnServerConfigChanged() { UpdatePortalRecipe(); } internal static void GameStarted() { KnownPortalsManager.Instance.Reset(); XPortalNetworksAdminSync.ResetForNewSession(); CustomNetworks.ResetSession(); RPCManager.Register(); if (Environment.IsServer) { CustomNetworks.InitializeServer(); } } internal static void OnPrePortalHover(out string result, ZDOID portalId, Vector3 location) { //IL_0005: 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_0012: 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_0023: 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_0069: 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) //IL_007e: 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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (!KnownPortalsManager.Instance.ContainsId(portalId)) { Log.Debug($"Hovering over new portal `{portalId}`"); KnownPortal portal = new KnownPortal(portalId, location); KnownPortalsManager.Instance.AddOrUpdate(portal); } KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(portalId); string friendlyName = knownPortalById.GetFriendlyName(); string friendlyTargetName = knownPortalById.GetFriendlyTargetName(); string text = string.Empty; if (knownPortalById.HasTarget()) { ZDOID target = knownPortalById.Target; if (!KnownPortalsManager.Instance.ContainsId(target)) { Log.Error($"Target portal {target} appears to be invalid"); SendToServer.SyncRequest($"Hovering over portal `{friendlyName}` which has invalid target `{target}`"); result = "Fetching portal info..."; return; } if (XPortalNetworksConfig.Instance.Local.DisplayPortalColour) { KnownPortal knownPortalById2 = KnownPortalsManager.Instance.GetKnownPortalById(knownPortalById.Target); text = "<color=" + knownPortalById2.Colour + ">>> </color>"; } } result = Localization.instance.Localize("$piece_portal_tag: " + friendlyName + "\n$piece_portal_target: " + text + friendlyTargetName + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_portal_settag"); } internal static void OnPortalRequestText(TeleportWorld teleportWorld) { //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_0016: 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) ZDOID uid = teleportWorld.m_nview.GetZDO().m_uid; if (!KnownPortalsManager.Instance.ContainsId(uid)) { Log.Error("Interacting with an unknown portal"); return; } KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(uid); Log.Debug($"Interacting with: {knownPortalById}"); Piece component = ((Component)teleportWorld).GetComponent<Piece>(); bool flag = XPortalNetworksAdminSync.IsLocalPortalNetworkAdmin(); bool num = (Object)(object)component != (Object)null && component.IsCreator(); bool canEditNetwork = num || flag; bool canEditPortalFully = num || flag; PortalConfigurationPanel.Instance.ConfigurePortal(knownPortalById, canEditNetwork, canEditPortalFully); } internal static void OnPortalPlaced(ZDOID portalId, Vector3 location) { //IL_0005: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Log.Debug($"Portal `{portalId}` was placed"); ZDOMan.instance.ForceSendZDO(portalId); KnownPortal knownPortal = new KnownPortal(portalId, location); KnownPortalsManager.Instance.AddOrUpdate(knownPortal); ZdoTools.UpdateFromKnownPortal(delayed: false, knownPortal); SendToServer.AddOrUpdateRequest(knownPortal); } internal static void OnPortalDestroyed(ZDOID portalId) { //IL_0005: 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_0012: 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_0056: Unknown result type (might be due to invalid IL or missing references) if (KnownPortalsManager.Instance.ContainsId(portalId)) { string name = KnownPortalsManager.Instance.GetKnownPortalById(portalId).Name; Log.Debug("Portal `" + name + "` is being destroyed"); KnownPortalsManager.Instance.Remove(portalId); } else { Log.Debug($"Portal `{portalId}` destroyed — was not in local known list; notifying server anyway"); } SendToServer.RemoveRequest(portalId); } internal static bool PrivateUseBlocked(ZDOID sourcePortalId, long playerId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!KnownPortalsManager.Instance.TryGetValue(sourcePortalId, out var portal) || !portal.HasTarget() || !KnownPortalsManager.Instance.TryGetValue(portal.Target, out var portal2) || !portal2.IsPrivate) { return false; } ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(portal2.Id) : null); long num = ((val != null) ? val.GetLong(ZDOVars.s_creator, 0L) : 0); bool num2 = num != 0L && num == playerId; bool flag = portal2.NetworkOwnerPlayerId != 0L && portal2.NetworkOwnerPlayerId == playerId; if (!num2) { return !flag; } return false; } internal static bool LocalPrivateUseBlocked(ZDOID sourcePortalId) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)null) { return PrivateUseBlocked(sourcePortalId, Player.m_localPlayer.GetPlayerID()); } return false; } internal static bool IsUsablePortal(TeleportWorld portal, Player player, bool originalFlag) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!originalFlag || (Object)(object)portal == (Object)null || (Object)(object)player == (Object)null || (Object)(object)portal.m_nview == (Object)null || !portal.m_nview.IsValid()) { return false; } ZDO zDO = portal.m_nview.GetZDO(); if (zDO == null) { return true; } return !PrivateUseBlocked(zDO.m_uid, player.GetPlayerID()); } internal static List<ZDO> ProcessSyncRequest(string reason) { List<ZDO> allPortalZDOs = GetAllPortalZDOs(); Log.Debug($"Fetched {allPortalZDOs.Count} portals"); ForceLocalPortalUpdate(allPortalZDOs); if (Environment.IsServer) { CustomNetworks.MigrateInvalidNetworks(); } SendToClient.Resync(KnownPortalsManager.Instance.Pack(), reason); return allPortalZDOs; } private static List<ZDO> GetAllPortalZDOs() { return ZDOMan.instance.GetPortalList(); } private static void ForceLocalPortalUpdate(List<ZDO> allPortals) { KnownPortalsManager.Instance.UpdateFromZDOList(allPortals); if (!Environment.IsServer) { string text = "Local portal list was updated"; Log.Debug("Send Sync Request, because: " + text); SendToServer.SyncRequest(text); } } internal static void PortalInfoSubmitted(KnownPortal portal, string newName, ZDOID newTarget, bool defaultPortal, long networkOwnerPlayerId, bool isPrivate) { //IL_0016: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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) if (defaultPortal) { isPrivate = false; XPortalNetworksConfig.Instance.Local.DefaultPortal.Value = portal.Location.Round(); } else if (portal.IsDefaultPortal) { XPortalNetworksConfig.Instance.Local.DefaultPortal.Value = Vector3.zero; } long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : Game.instance.GetPlayerProfile().GetPlayerID()); long num2 = networkOwnerPlayerId; if (isPrivate) { num2 = ((networkOwnerPlayerId != 0L && !CustomNetworks.IsReservedIdRange(networkOwnerPlayerId)) ? networkOwnerPlayerId : num); } string text = portal.NetworkOwnerDisplayName ?? string.Empty; if (num2 == 0L) { text = string.Empty; } else if (CustomNetworks.IsReservedIdRange(num2)) { text = (CustomNetworks.TryGetDisplayName(num2, out var displayName) ? displayName : string.Empty); } else if (num2 == num) { text = PortalNetwork.SanitizeNetworkOwnerDisplayName(((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : Game.instance.GetPlayerProfile().GetName()); } bool flag = portal.NetworkOwnerPlayerId != num2; bool num3 = !portal.Name.Equals(newName) || !portal.Targets(newTarget); bool flag2 = !string.Equals(portal.NetworkOwnerDisplayName ?? string.Empty, text, StringComparison.Ordinal); bool flag3 = portal.IsPrivate != isPrivate; if (num3 || flag || flag2 || flag3) { portal.Name = newName; portal.Target = newTarget; portal.NetworkOwnerPlayerId = num2; portal.NetworkOwnerDisplayName = text; portal.IsPrivate = isPrivate; Log.Debug("Updating portal `" + portal.Name + "`"); SendToServer.AddOrUpdateRequest(portal); } } internal static void PingMapButtonClicked(ZDOID targetId) { //IL_0017: 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_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) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!XPortalNetworksConfig.Instance.Server.PingMapDisabled) { KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(targetId); Log.Debug($"Pinging portal: {knownPortalById}"); string friendlyName = knownPortalById.GetFriendlyName(); Vector3 location = knownPortalById.Location; SendToClient.PingMap(location, friendlyName); Minimap.instance.ShowPointOnMap(location); } } } internal static class ZdoTools { public static string GetName(ZDO portalZdo) { return portalZdo.GetString("tag", ""); } public static void SetName(ZDO portalZdo, string name) { portalZdo.Set("tag", name); } public static void SetOwner(ZDO portalZdo) { portalZdo.SetOwner(ZDOMan.GetSessionID()); } public static void SetPreviousId(ZDO portalZdo) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) portalZdo.Set("XPortalNetworks_PreviousId", portalZdo.m_uid); } public static void SetTarget(ZDO portalZdo, ZDOID targetId) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) portalZdo.Set("XPortalNetworks_TargetId", targetId); portalZdo.SetConnection((ConnectionType)1, targetId); } public static long GetNetworkOwnerPlayerId(ZDO portalZdo) { return portalZdo.GetLong("XPortalNetworks_NetworkOwnerPlayerId", 0L); } public static void SetNetworkOwnerPlayerId(ZDO portalZdo, long ownerPlayerId) { portalZdo.Set("XPortalNetworks_NetworkOwnerPlayerId", ownerPlayerId); } public static string GetNetworkOwnerDisplayName(ZDO portalZdo) { return portalZdo.GetString("XPortalNetworks_NetworkOwnerDisplayName", ""); } public static void SetNetworkOwnerDisplayName(ZDO portalZdo, string displayName) { portalZdo.Set("XPortalNetworks_NetworkOwnerDisplayName", displayName ?? string.Empty); } public static bool GetIsPrivate(ZDO portalZdo) { return portalZdo.GetBool("XPortalNetworks_IsPrivate", false); } public static void SetIsPrivate(ZDO portalZdo, bool isPrivate) { portalZdo.Set("XPortalNetworks_IsPrivate", isPrivate); } public static void UpdateFromKnownPortal(bool delayed = false, object state = null) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if (delayed) { QueuedAction.Queue(UpdateFromKnownPortal, 1); return; } KnownPortal knownPortal = (KnownPortal)state; ZDO zDO = ZDOMan.instance.GetZDO(knownPortal.Id); if (zDO == null) { Log.Debug("Portal ZDO not found, trying again with delay.."); QueuedAction.Queue(UpdateFromKnownPortal, 3, knownPortal); return; } SetOwner(zDO); SetName(zDO, knownPortal.Name); SetPreviousId(zDO); SetNetworkOwnerPlayerId(zDO, knownPortal.NetworkOwnerPlayerId); SetNetworkOwnerDisplayName(zDO, knownPortal.NetworkOwnerDisplayName ?? string.Empty); SetIsPrivate(zDO, knownPortal.IsPrivate); SetTarget(zDO, knownPortal.Target); } } } namespace XPortalNetworks.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("XPortal.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal Resources() { } } } namespace XPortalNetworks.UI { internal sealed class PortalConfigurationPanel : IDisposable { private sealed class ListFocusState { public Dropdown Target; public int Row; } private static readonly Lazy<PortalConfigurationPanel> lazy = new Lazy<PortalConfigurationPanel>(() => new PortalConfigurationPanel()); internal const string GO_MAINPANEL = "XPortalNetworks_MainPanel"; internal const string GO_HEADERTEXT = "XPortalNetworks_PanelHeader"; internal const string GO_NAMELABEL = "XPortalNetworks_NameHeader"; internal const string GO_NAMEINPUT = "XPortalNetworks_NameInput"; internal const string GO_DESTINATIONLABEL = "XPortalNetworks_DestinationHeader"; internal const string GO_DESTINATIONDROPDOWN = "XPortalNetworks_DestinationDropdown"; internal const string GO_DESTINATIONGAMEPADHINT = "XPortalNetworks_DestinationGamepadHint"; internal const string GO_NETWORKASSIGNLISTNAVHINT = "XPortalNetworks_NetworkAssignListNavHint"; internal const string GO_DESTINATIONNETWORKLISTNAVHINT = "XPortalNetworks_DestinationNetworkListNavHint"; internal const string GO_PINGMAPBUTTON = "XPortalNetworks_PingMapButton"; internal const string GO_DEFAULTPORTALLABEL = "XPortalNetworks_DefaultPortalHeader"; internal const string GO_DEFAULTPORTALCHECKBOX = "XPortalNetworks_DefaultPortalCheckbox"; internal const string GO_PRIVATEPORTALLABEL = "XPortalNetworks_PrivatePortalHeader"; internal const string GO_PRIVATEPORTALCHECKBOX = "XPortalNetworks_PrivatePortalCheckbox"; internal const string GO_OKAYBUTTON = "XPortalNetworks_OkayButton"; internal const string GO_CANCELBUTTON = "XPortalNetworks_CancelButton"; internal const string GO_NETWORKASSIGNLABEL = "XPortalNetworks_NetworkAssignHeader"; internal const string GO_NETWORKASSIGNDROPDOWN = "XPortalNetworks_NetworkAssignDropdown"; internal const string GO_DESTINATIONNETWORKLABEL = "XPortalNetworks_DestinationNetworkHeader"; internal const string GO_DESTINATIONNETWORKDROPDOWN = "XPortalNetworks_DestinationNetworkDropdown"; private static readonly float padding = 24f; private static readonly float rowHeight = 32f; private static readonly float labelWidth = 160f; private static readonly float buttonWidth = 90f; private static readonly float submitButtonWidth = 110f; private static readonly float submitButtonHeight = 48f; private static readonly float inputShortWidth = 460f; private static readonly float inputLongWidth = inputShortWidth + padding + buttonWidth; private static readonly float rowStep = rowHeight + padding; private static readonly float networkAssignRowTop = -60f - padding; private static readonly float nameRowTop = networkAssignRowTop - rowStep; private static readonly float destinationNetworkRowTop = nameRowTop - rowStep; private static readonly float destinationPortalRowTop = destinationNetworkRowTop - rowStep; private static readonly float privatePortalRowTop = destinationPortalRowTop - rowStep; private static readonly float defaultPortalRowTop = privatePortalRowTop - rowStep; private static readonly float firstColumnLeft = 0f + padding; private static readonly float secondColumnLeft = firstColumnLeft + labelWidth + padding; private GameObject mainPanel; private GameObject pingMapButtonObject; private GameObject targetPortalDropdownObject; private Dropdown targetPortalDropdown; private readonly List<GameObject> dropdownListNavHints = new List<GameObject>(); private InputField portalNameInputField; private Toggle defaultPortalToggle; private Toggle privatePortalToggle; private Button okayButton; private Dropdown networkAssignmentDropdown; private Dropdown destinationNetworkDropdown; private readonly Dictionary<int, ZDOID> dropdownIndexToZDOIDMapping; private readonly Dictionary<int, long> destinationNetworkIndexToOwnerId = new Dictionary<int, long>(); private readonly Dictionary<int, long> networkAssignmentIndexToOwnerId = new Dictionary<int, long>(); private int personalNetworkAssignmentIndex; private KnownPortal thisPortal; private ZDOID selectedTargetId; private long selectedDestinationNetworkOwnerId; private bool canEditNetworkAssignment; private bool canEditPortalFully; private bool readOnlyPrivatePortal; private ButtonConfig uiDropdownScrollUpButton; private ButtonConfig uiDropdownScrollDownButton; private static ScrollRect listScrollCache; private Dropdown lastSyncedScrollDropdown; private int lastSyncedListScroll = int.MinValue; private float listNavNextTime; private const float ListNavInitialDelay = 0.22f; private const float ListNavRepeatInterval = 0.065f; private const float ListWheelSensFloor = 520f; private const float ListBottomSlackPx = 14f; private const string ListBottomSpacerName = "XPortal_DropdownListBottomSpacer"; private const float ListBottomSpacerH = 64f; private static FieldInfo dropdownItemsField; private static MethodInfo scrollRectUpdateBounds; public static PortalConfigurationPanel Instance => lazy.Value; public Dropdown ExpandedDropdown { get; private set; } public bool DropdownExpanded => (Object)(object)ExpandedDropdown != (Object)null; private PortalConfigurationPanel() { dropdownIndexToZDOIDMapping = new Dictionary<int, ZDOID>(); } internal static bool IsManagedDropdown(Dropdown d) { if ((Object)(object)d != (Object)null) { return IsManagedDropdownName(((Object)d).name); } return false; } internal static bool IsManagedDropdownName(string name) { if (!(name == "XPortalNetworks_DestinationDropdown") && !(name == "XPortalNetworks_NetworkAssignDropdown")) { return name == "XPortalNetworks_DestinationNetworkDropdown"; } return true; } internal void SetExpandedDropdown(Dropdown d) { ExpandedDropdown = d; } internal void ClearExpandedDropdownIf(Dropdown d) { if ((Object)(object)ExpandedDropdown == (Object)(object)d) { ExpandedDropdown = null; } } internal static void QueueListScroll(Dropdown dropdown) { if (!((Object)(object)dropdown == (Object)null)) { QueuedAction.Queue(DeferredListScroll, 1, dropdown); QueuedAction.Queue(DeferredListScroll, 2, dropdown); } } private static void DeferredListScroll(bool unused, object state) { ApplyListScroll((Dropdown)((state is Dropdown) ? state : null)); } internal static void ApplyListScroll(Dropdown dropdown, bool rebuildLayout = true) { if (((dropdown != null) ? dropdown.options : null) == null || dropdown.options.Count == 0) { return; } ScrollRect val = FindListScrollRect(dropdown); if ((Object)(object)val == (Object)null) { return; } val.scrollSensitivity = Mathf.Max(val.scrollSensitivity, 520f); int num = Mathf.Clamp(dropdown.value, 0, dropdown.options.Count - 1); RectTransform content = val.content; if (!((Object)(object)content == (Object)null) && ((Transform)content).childCount != 0) { if (rebuildLayout) { LayoutRebuilder.ForceRebuildLayoutImmediate(content); Canvas.ForceUpdateCanvases(); } int count = dropdown.options.Count; int num2 = Mathf.Max(0, count - 1); int num3 = Mathf.Clamp(num, 0, num2); float normalized = ((num2 <= 0) ? 1f : ((num3 >= num2) ? 0f : ((num3 > 0) ? (1f - (float)num3 / (float)num2) : 1f))); SetScrollNorm(val, normalized); if (num3 >= ((Transform)content).childCount) { FocusListRow(dropdown, num3); QueueListFocus(dropdown, num3); return; } Transform child = ((Transform)content).GetChild(num3); RectTransform item = (RectTransform)(object)((child is RectTransform) ? child : null); NudgeRowIntoView(val, content, item); FocusListRow(dropdown, num3); QueueListFocus(dropdown, num3); } } private static Toggle ItemToggle(Dropdown dropdown, int index) { if ((Object)(object)dropdown == (Object)null || index < 0) { return null; } if (dropdownItemsField == null) { dropdownItemsField = typeof(Dropdown).GetField("m_Items", BindingFlags.Instance | BindingFlags.NonPublic); } if (dropdownItemsField == null) { return null; } if (!(dropdownItemsField.GetValue(dropdown) is IList list) || index >= list.Count) { return null; } object obj = list[index]; if (obj == null) { return null; } Type type = obj.GetType(); FieldInfo field = type.GetField("toggle", BindingFlags.Instance | BindingFlags.Public); if (field != null) { object? value = field.GetValue(obj); return (Toggle)((value is Toggle) ? value : null); } object? obj2 = type.GetProperty("toggle", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj, null); return (Toggle)((obj2 is Toggle) ? obj2 : null); } private static void FocusListRow(Dropdown dropdown, int rowIndex) { if (Instance == null || (Object)(object)Instance.ExpandedDropdown != (Object)(object)dropdown || (Object)(object)dropdown == (Object)null || rowIndex < 0 || rowIndex >= dropdown.options.Count) { return; } Toggle val = ItemToggle(dropdown, rowIndex); if ((Object)(object)val == (Object)null) { ScrollRect obj = FindListScrollRect(dropdown); RectTransform val2 = ((obj != null) ? obj.content : null); if ((Object)(object)val2 != (Object)null && rowIndex < ((Transform)val2).childCount) { Transform child = ((Transform)val2).GetChild(rowIndex); val = ((Component)child).GetComponent<Toggle>() ?? ((Component)child).GetComponentInChildren<Toggle>(true); } } if (!((Object)(object)val == (Object)null)) { EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null) { current.SetSelectedGameObject(((Component)val).gameObject); } else { ((Selectable)val).Select(); } } } private static void QueueListFocus(Dropdown dropdown, int rowIndex) { if (!((Object)(object)dropdown == (Object)null)) { ListFocusState state = new ListFocusState { Target = dropdown, Row = rowIndex }; QueuedAction.Queue(DeferredListFocus, 0, state); QueuedAction.Queue(DeferredListFocus, 1, state); QueuedAction.Queue(DeferredListFocus, 2, state); } } private static void DeferredListFocus(bool unused, object state) { if (state is ListFocusState listFocusState) { FocusListRow(listFocusState.Target, listFocusState.Row); } } internal static void ClearListScroll() { listScrollCache = null; if (Instance != null) { Instance.lastSyncedScrollDropdown = null; Instance.lastSyncedListScroll = int.MinValue; Instance.listNavNextTime = 0f; } } internal void SyncListScroll() { if (!((Object)(object)ExpandedDropdown == (Object)null)) { int value = ExpandedDropdown.value; if (!((Object)(object)ExpandedDropdown == (Object)(object)lastSyncedScrollDropdown) || value != lastSyncedListScroll) { lastSyncedScrollDropdown = ExpandedDropdown; lastSyncedListScroll = value; ApplyListScroll(ExpandedDropdown); } } } private static void UpdateScrollBounds(ScrollRect scrollRect) { if (scrollRectUpdateBounds == null) { scrollRectUpdateBounds = typeof(ScrollRect).GetMethod("UpdateBounds", BindingFlags.Instance | BindingFlags.NonPublic); } scrollRectUpdateBounds?.Invoke(scrollRect, null); } private static void SetScrollNorm(ScrollRect scrollRect, float normalized) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) normalized = Mathf.Clamp01(normalized); scrollRect.verticalNormalizedPosition = normalized; scrollRect.StopMovement(); scrollRect.velocity = Vector2.zero; UpdateScrollBounds(scrollRect); Canvas.ForceUpdateCanvases(); if ((Object)(object)scrollRect.verticalScrollbar != (Object)null) { scrollRect.verticalScrollbar.SetValueWithoutNotify(normalized); } } private static Camera CanvasCamera(Canvas canvas) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)canvas == (Object)null) { return null; } if ((int)canvas.renderMode == 0) { return null; } return canvas.worldCamera; } private static void ExtentsFromBounds(RectTransform item, Camera cam, Bounds lb, out float worldBottom, out float worldTop, out float screenMinY, out float screenMaxY) { //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_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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Vector3 center = ((Bounds)(ref lb)).center; Vector3 extents = ((Bounds)(ref lb)).extents; worldBottom = float.MaxValue; worldTop = float.MinValue; screenMinY = float.MaxValue; screenMaxY = float.MinValue; for (int i = 0; i < 8; i++) { Vector3 val = center + new Vector3(((i & 1) != 0) ? extents.x : (0f - extents.x), ((i & 2) != 0) ? extents.y : (0f - extents.y), ((i & 4) != 0) ? extents.z : (0f - extents.z)); Vector3 val2 = ((Transform)item).TransformPoint(val); worldBottom = Mathf.Min(worldBottom, val2.y); worldTop = Mathf.Max(worldTop, val2.y); float y = RectTransformUtility.WorldToScreenPoint(cam, val2).y; screenMinY = Mathf.Min(screenMinY, y); screenMaxY = Mathf.Max(screenMaxY, y); } } private static float CornersMinScreenY(Vector3[] corners, Camera cam) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; for (int i = 0; i < 4; i++) { num = Mathf.Min(num, RectTransformUtility.WorldToScreenPoint(cam, corners[i]).y); } return num; } private static float CornersMaxScreenY(Vector3[] corners, Camera cam) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = float.MinValue; for (int i = 0; i < 4; i++) { num = Mathf.Max(num, RectTransformUtility.WorldToScreenPoint(cam, corners[i]).y); } return num; } private static void NudgeRowIntoView(ScrollRect scrollRect, RectTransform content, RectTransform item) { //IL_0053: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) RectTransform viewport = scrollRect.viewport; if ((Object)(object)viewport == (Object)null || (Object)(object)content == (Object)null || (Object)(object)item == (Object)null) { return; } Canvas componentInParent = ((Component)viewport).GetComponentInParent<Canvas>(); Camera cam = CanvasCamera(componentInParent); Transform parent = ((Transform)content).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); Vector3[] array = (Vector3[])(object)new Vector3[4]; for (int i = 0; i < 28; i++) { Canvas.ForceUpdateCanvases(); Bounds lb = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)item); ExtentsFromBounds(item, cam, lb, out var worldBottom, out var worldTop, out var screenMinY, out var screenMaxY); viewport.GetWorldCorners(array); float num = Mathf.Min(array[0].y, array[3].y); float num2 = Mathf.Max(array[1].y, array[2].y); float num3 = 0f; if ((Object)(object)componentInParent != (Object)null) { Rect rect = viewport.rect; float num4 = Mathf.Max(1f, ((Rect)(ref rect)).height * componentInParent.scaleFactor); float num5 = Mathf.Abs(num2 - num); num3 = 14f / num4 * Mathf.Max(num5, 0.0001f); } float num6 = CornersMinScreenY(array, cam); float num7 = CornersMaxScreenY(array, cam); bool flag = screenMinY >= num6 - 14f - 0.5f; bool flag2 = screenMaxY <= num7 + 0.5f; if (worldBottom >= num - 0.5f - num3 && worldTop <= num2 + 0.5f && flag && flag2) { scrollRect.StopMovement(); scrollRect.velocity = Vector2.zero; return; } float num8 = 0f; if (worldBottom < num - 0.5f - num3 || !flag) { num8 = num - worldBottom - num3; } else if (worldTop > num2 + 0.5f || !flag2) { num8 = num2 - worldTop; } if (Mathf.Abs(num8) < 0.005f) { break; } if ((Object)(object)val != (Object)null) { Vector2 val2 = Vector2.op_Implicit(((Transform)val).InverseTransformVector(new Vector3(0f, num8, 0f))); content.anchoredPosition += new Vector2(0f, val2.y); } else { Vector3 val3 = ((Transform)content).InverseTransformVector(new Vector3(0f, num8, 0f)); content.anchoredPosition += new Vector2(0f, val3.y); } scrollRect.StopMovement(); scrollRect.velocity = Vector2.zero; UpdateScrollBounds(scrollRect); } Canvas.ForceUpdateCanvases(); } private static ScrollRect FindListScrollRect(Dropdown dropdown) { if ((Object)(object)listScrollCache != (Object)null && Object.op_Implicit((Object)(object)listScrollCache)) { return listScrollCache; } Transform[] componentsInChildren = ((Component)((Component)dropdown).transform.root).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Component)val).gameObject.activeInHierarchy && ((Object)val).name.IndexOf("Dropdown List", StringComparison.Ordinal) >= 0) { ScrollRect val2 = ((Component)val).GetComponent<ScrollRect>() ?? ((Component)val).GetComponentInChildren<ScrollRect>(true); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.content != (Object)null) { listScrollCache = val2; return val2; } } } object obj = typeof(Dropdown).GetField("m_Dropdown", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(dropdown); object obj2 = ((obj is GameObject) ? obj : null); if (obj2 == null) { object obj3 = ((obj is Component) ? obj : null); obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null); } GameObject val3 = (GameObject)obj2; if ((Object)(object)val3 == (Object)null || !val3.activeInHierarchy) { return null; } ScrollRect val4 = val3.GetComponent<ScrollRect>() ?? val3.GetComponentInChildren<ScrollRect>(true); if ((Object)(object)val4 != (Object)null) { listScrollCache = val4; } return val4; } internal void AddInputs() { uiDropdownScrollUpButton = AddInput("XPortal_DropdownScrollUp", "$settings_dropdown_scrollup", (GamepadButton)1, (KeyCode)273); uiDropdownScrollDownButton = AddInput("XPortal_DropdownScrollDown", "$settings_dropdown_scrolldown", (GamepadButton)2, (KeyCode)274); } private ButtonConfig AddInput(string name, string hintToken, GamepadButton gamepadButton, KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) //IL_0021: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown ButtonConfig val = new ButtonConfig { Name = name, HintToken = hintToken, ActiveInGUI = true, ActiveInCustomGUI = true, Key = key, GamepadButton = gamepadButton, RepeatDelay = 1000f, BlockOtherInputs = true }; InputManager.Instance.AddButton("vapok.mods.xportalnetworks", val); return val; } public void HandleInput() { bool flag = ZInput.IsGamepadActive(); for (int i = 0; i < dropdownListNavHints.Count; i++) { GameObject val = dropdownListNavHints[i]; if (Object.op_Implicit((Object)(object)val)) { Dropdown val2 = (((Object)(object)val.transform.parent != (Object)null) ? ((Component)val.transform.parent).GetComponent<Dropdown>() : null); bool active = flag && (Object)(object)val2 != (Object)null && (Object)(object)ExpandedDropdown == (Object)(object)val2; val.SetActive(active); } } ProcessListNav(); } private void ProcessListNav() { if ((Object)(object)ExpandedDropdown == (Object)null) { listNavNextTime = 0f; return; } bool flag = ZInput.GetButton(uiDropdownScrollUpButton.Name); bool flag2 = ZInput.GetButton(uiDropdownScrollDownButton.Name); if (ZInput.IsGamepadActive()) { flag = flag || ZInput.GetButton("JoyLStickUp") || ZInput.GetButton("JoyDPadUp"); flag2 = flag2 || ZInput.GetButton("JoyLStickDown") || ZInput.GetButton("JoyDPadDown"); } if (flag && flag2) { listNavNextTime = 0f; return; } if (!flag && !flag2) { listNavNextTime = 0f; return; } float unscaledTime = Time.unscaledTime; if (listNavNextTime <= 0f) { BumpDropdown(flag); listNavNextTime = unscaledTime + 0.22f; } else if (unscaledTime >= listNavNextTime) { BumpDropdown(flag); listNavNextTime = unscaledTime + 0.065f; } } public bool IsActive() { if (Object.op_Implicit((Object)(object)mainPanel)) { return mainPanel.activeSelf; } return false; } public void SetActive(bool active) { if (!Object.op_Implicit((Object)(object)mainPanel) || !GameObjectExtension.IsValid(mainPanel)) { InitialiseUI(); } GUIManager.BlockInput(active); mainPanel.SetActive(active); if (active) { ActivateInputField(); } } private void ActivateInputField(bool delayed = true, object state = null) { if (delayed) { QueuedAction.Queue(ActivateInputField); } else { portalNameInputField.ActivateInputField(); } } public void Show() { SetActive(active: true); } public void Hide(bool delayed = true, object state = null) { if (delayed) { QueuedAction.Queue(Hide); } else { SetActive(active: false); } } private void BumpDropdown(bool up) { Dropdown expandedDropdown = ExpandedDropdown; if ((Object)(object)expandedDropdown == (Object)null) { return; } int num = expandedDropdown.options.Count - 1; if (num >= 0) { int num2 = Mathf.Clamp(expandedDropdown.value + ((!up) ? 1 : (-1)), 0, num); if (num2 != expandedDropdown.value) { expandedDropdown.value = num2; } } } private void SetPingMapButtonActive(bool active) { //IL_004d: 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_006d: Unknown result type (might be due to invalid IL or missing references) if (ZoneSystem.instance.GetGlobalKey("nomap") || XPortalNetworksConfig.Instance.Server.PingMapDisabled) { active = false; } pingMapButtonObject.SetActive(active); RectTransform component = mainPanel.GetComponent<RectTransform>(); float num = (active ? inputShortWidth : inputLongWidth); Rect rect = component.rect; float num2 = num - ((Rect)(ref rect)).width; targetPortalDropdownObject.GetComponent<RectTransform>().sizeDelta = new Vector2(num2, rowHeight); } public void ConfigurePortal(KnownPortal portal, bool canEditNetwork, bool canEditPortalFully) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) InitialiseUI(); thisPortal = portal; canEditNetworkAssignment = canEditNetwork; this.canEditPortalFully = canEditPortalFully; readOnlyPrivatePortal = portal.IsPrivate && !canEditPortalFully; portalNameInputField.text = portal.Name; selectedTargetId = portal.Target; defaultPortalToggle.isOn = thisPortal.IsDefaultPortal; privatePortalToggle.isOn = thisPortal.IsPrivate; if (defaultPortalToggle.isOn) { privatePortalToggle.SetIsOnWithoutNotify(false); } ((UnityEventBase)defaultPortalToggle.onValueChanged).RemoveAllListeners(); ((UnityEvent<bool>)(object)defaultPortalToggle.onValueChanged).AddListener((UnityAction<bool>)OnDefaultPortalToggleChanged); ((UnityEventBase)privatePortalToggle.onValueChanged).RemoveAllListeners(); ((UnityEvent<bool>)(object)privatePortalToggle.onValueChanged).AddListener((UnityAction<bool>)OnPrivatePortalToggleChanged); PopulateNetworkAssignmentDropdown(); PopulateDestinationNetworkDropdown(); PopulateDestinationPortalDropdown(); ApplyReadOnlyState(); Show(); } private void ApplyReadOnlyState() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) readOnlyPrivatePortal = thisPortal.IsPrivate && !canEditPortalFully; bool flag = !readOnlyPrivatePortal; ((Selectable)portalNameInputField).interactable = flag; ((Selectable)targetPortalDropdown).interactable = flag; ((Selectable)destinationNetworkDropdown).interactable = flag; ((Selectable)networkAssignmentDropdown).interactable = canEditNetworkAssignment && flag; ((Selectable)defaultPortalToggle).interactable = flag; ((Selectable)privatePortalToggle).interactable = canEditPortalFully && flag && !defaultPortalToggle.isOn; if ((Object)(object)okayButton != (Object)null) { ((Selectable)okayButton).interactable = flag; } Button val = (((Object)(object)pingMapButtonObject != (Object)null) ? pingMapButtonObject.GetComponent<Button>() : null); if ((Object)(object)val != (Object)null) { ((Selectable)val).interactable = flag && selectedTargetId != ZDOID.None; } } private void OnDefaultPortalToggleChanged(bool isOn) { if (isOn) { privatePortalToggle.SetIsOnWithoutNotify(false); } ApplyReadOnlyState(); } private void OnPrivatePortalToggleChanged(bool isOn) { if (isOn) { defaultPortalToggle.SetIsOnWithoutNotify(false); } if (canEditNetworkAssignment && isOn) { networkAssignmentDropdown.SetValueWithoutNotify(personalNetworkAssignmentIndex); } } internal void OnNetworksListChanged() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (IsActive() && thisPortal != null && KnownPortalsManager.Instance.TryGetValue(thisPortal.Id, out var portal)) { thisPortal = portal; PopulateNetworkAssignmentDropdown(); PopulateDestinationNetworkDropdown(); PopulateDestinationPortalDropdown(); ApplyReadOnlyState(); } } private int FindNetworkAssignmentDropdownIndex(long networkOwnerPlayerId) { foreach (KeyValuePair<int, long> item in networkAssignmentIndexToOwnerId) { if (item.Value == networkOwnerPlayerId) { return item.Key; } } return -1; } private void PopulateNetworkAssignmentDropdown() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown ((UnityEventBase)networkAssignmentDropdown.onValueChanged).RemoveAllListeners(); networkAssignmentDropdown.ClearOptions(); networkAssignmentIndexToOwnerId.Clear(); if (!canEditNetworkAssignment) { networkAssignmentDropdown.options.Add(new OptionData(PortalNetwork.FormatNetworkLabel(thisPortal.NetworkOwnerPlayerId))); networkAssignmentDropdown.value = 0; ((Selectable)networkAssignmentDropdown).interactable = false; ApplyDropdownStyle(networkAssignmentDropdown); networkAssignmentDropdown.RefreshShownValue(); return; } ((Selectable)networkAssignmentDropdown).interactable = true; long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : Game.instance.GetPlayerProfile().GetPlayerID()); int num2 = -1; networkAssignmentDropdown.options.Add(new OptionData(PortalNetwork.FormatNetworkLabel(0L))); networkAssignmentIndexToOwnerId.Add(++num2, 0L); foreach (long sortedActiveId in CustomNetworks.GetSortedActiveIds()) { networkAssignmentDropdown.options.Add(new OptionData(PortalNetwork.FormatNetworkLabel(sortedActiveId))); networkAssignmentIndexToOwnerId.Add(++num2, sortedActiveId); } networkAssignmentDropdown.options.Add(new OptionData(PortalNetwork.FormatNetworkLabel(num))); networkAssignmentIndexToOwnerId.Add(++num2, num); personalNetworkAssignmentIndex = num2; if (thisPortal.NetworkOwnerPlayerId != 0L && thisPortal.NetworkOwnerPlayerId != num && !CustomNetworks.IsReservedIdRange(thisPortal.NetworkOwnerPlayerId)) { networkAssignmentDropdown.options.Add(new OptionData(PortalNetwork.FormatNetworkLabel(thisPortal.NetworkOwnerPlayerId))); networkAssignmentIndexToOwnerId.Add(++num2, thisPortal.NetworkOwnerPlayerId); } if (thisPortal.IsPrivate) { int num3 = FindNetworkAssignmentDropdownIndex(thisPortal.NetworkOwnerPlayerId); networkAssignmentDropdown.value = ((num3 >= 0) ? num3 : personalNetworkAssignmentIndex); } else { int num4 = FindNetworkAssignmentDropdownIndex(thisPortal.NetworkOwnerPlayerId); networkAssignmentDropdown.value = ((num4 >= 0) ? num4 : 0); } ApplyDropdownStyle(networkAssignmentDropdown); networkAssignmentDropdown.RefreshShownValue(); ((UnityEvent<int>)(object)networkAssignmentDropdown.onValueChanged).AddListener((UnityAction<int>)delegate { OnNetworkAssignmentDropdownValueChanged(networkAssignmentDropdown); }); } private void OnNetworkAssignmentDropdownValueChanged(Dropdown change) { if (networkAssignmentIndexToOwnerId.TryGetValue(change.value, out var value) && (value == 0L || CustomNetworks.IsReservedIdRange(value)) && privatePortalToggle.isOn) { privatePortalToggle.SetIsOnWithoutNotify(false); } } private long GetSubmittedNetworkOwnerPlayerId() { if (!canEditNetworkAssignment) { return thisPortal.NetworkOwnerPlayerId; } if (!networkAssignmentIndexToOwnerId.