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 XPortalNetworksTribesPins v3.1.1
plugins\XPortalNetworks.dll
Decompiled 44 minutes 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 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("XPortalNetworksTribesPins")] [assembly: AssemblyDescription("Select portal destination from a list of existing portals with custom networks with private portal and tribe restrictions. No more tag pairing, and no more portal hubs! Also manages map pins for the portals a player is allowed to use.")] [assembly: AssemblyCompany("ghstwhl")] [assembly: AssemblyProduct("XPortalNetworksTribesPins")] [assembly: AssemblyFileVersion("3.1.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("3.1.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 = "ghostwheel.mods.xportalnetworkstribespins"; public const string HarmonyGUID = "ghostwheel.mods.xportalnetworkstribespins.harmony"; public const string LegacyGUID = "vapok.mods.xportalnetworks"; public const string Author = "ghstwhl"; public const string Name = "XPortalNetworksTribesPins"; public const string LegacyName = "XPortalNetworks"; public const string HumanName = "XPortal Networks Tribes Pins"; public const string GitHubRepo = "ghstwhl/XPortalNetworksTribesPins"; public const string ThunderstoreTeam = "NorCal_Nerds"; public const string ThunderstorePackage = "XPortalNetworksTribesPins"; public const string Version = "3.1.1"; public const string Description = "Select portal destination from a list of existing portals with custom networks with private portal and tribe restrictions. No more tag pairing, and no more portal hubs! Also manages map pins for the portals a player is allowed to use."; public const string WebsiteUrl = "https://github.com/ghstwhl/XPortalNetworksTribesPins"; public const int NexusId = 4092; public const string BepInExPackVersion = "5.4.2350"; public const string JotunnVersion = "2.30.2"; } } namespace XPortalNetworks { internal static class Environment { private static bool? _isHeadless; internal static bool IsServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } internal static bool IsHeadless { get { if (_isHeadless.HasValue) { return _isHeadless.Value; } _isHeadless = GUIManager.IsHeadless(); return _isHeadless.Value; } } internal static bool GameStarted { get; set; } internal static bool ShuttingDown { get { if (!((Object)(object)Game.instance == (Object)null)) { return Game.instance.m_shuttingDown; } return true; } } internal static long ServerPeerId { get { if (ZRoutedRpc.instance == null) { return 0L; } return ZRoutedRpc.instance.GetServerPeerID(); } } } internal static class CustomNetworks { internal sealed class PortalNetworkDefinition { internal long Id { get; } internal string Name { get; } internal IReadOnlyList<string> AllowList { get; } internal bool IsOpen { get { if (AllowList != null) { return AllowList.Count == 0; } return true; } } internal PortalNetworkDefinition(long id, string name, IReadOnlyList<string> allowList) { Id = id; Name = name ?? string.Empty; AllowList = allowList ?? Array.Empty<string>(); } internal bool Allows(params string[] playerIdentifiers) { if (IsOpen) { return true; } foreach (string allow in AllowList) { if (string.IsNullOrWhiteSpace(allow)) { continue; } foreach (string text in playerIdentifiers) { if (!string.IsNullOrWhiteSpace(text) && string.Equals(allow.Trim(), text.Trim(), StringComparison.OrdinalIgnoreCase)) { return true; } } } return false; } } internal const int MinId = 1; internal const int MaxId = 15; internal const string LegacyConfigFileName = "xportal_networks.json"; private static readonly UTF8Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); private static readonly Dictionary<long, PortalNetworkDefinition> ActiveById = new Dictionary<long, PortalNetworkDefinition>(); private static readonly Regex NetworkObjectRegex = new Regex("\\{[^{}]*\\}", RegexOptions.Compiled | RegexOptions.CultureInvariant); private static readonly Regex NetworkIdRegex = new Regex("\"id\"\\s*:\\s*(\\d+)", RegexOptions.Compiled | RegexOptions.CultureInvariant); private static readonly Regex NetworkNameRegex = new Regex("\"name\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"", RegexOptions.Compiled | RegexOptions.CultureInvariant); private static readonly Regex NetworkAllowListRegex = new Regex("\"allow_list\"\\s*:\\s*\\[(.*?)\\]", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant); private static readonly Regex JsonStringRegex = new Regex("\"((?:[^\"\\\\]|\\\\.)*)\"", RegexOptions.Compiled | RegexOptions.CultureInvariant); internal static bool AdminsBypassNetworks => XPortalNetworksConfig.Instance.Local.AdminsSeeAllNetworks; internal static event Action ListChanged; internal static void ResetSession() { RebuildFromConfig(notify: false); } internal static void RebuildFromConfig(bool notify = true) { Dictionary<long, PortalNetworkDefinition> dictionary = new Dictionary<long, PortalNetworkDefinition>(); XPortalNetworksConfig instance = XPortalNetworksConfig.Instance; for (int i = 1; i <= 15; i++) { string networkName = instance.GetNetworkName(i); if (!string.IsNullOrWhiteSpace(networkName)) { string text = PortalNetwork.SanitizeNetworkOwnerDisplayName(networkName); if (string.IsNullOrEmpty(text)) { Log.Warning($"Portal network {i}: name `{networkName}` is invalid after sanitization; ignoring this network."); } else { dictionary[i] = new PortalNetworkDefinition(i, text, ParseAllowListSetting(instance.GetNetworkAllowList(i), i)); } } } lock (ActiveById) { ActiveById.Clear(); foreach (KeyValuePair<long, PortalNetworkDefinition> item in dictionary) { ActiveById[item.Key] = item.Value; } } Log.Debug($"Portal networks rebuilt from config: {dictionary.Count} active."); if (notify) { CustomNetworks.ListChanged?.Invoke(); } } private static IReadOnlyList<string> ParseAllowListSetting(string raw, long id) { List<string> list = new List<string>(); if (string.IsNullOrWhiteSpace(raw)) { return list; } string[] array = raw.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = PortalNetwork.SanitizeNetworkOwnerDisplayName(array[i].Trim()); if (!string.IsNullOrEmpty(text) && !list.Contains<string>(text, StringComparer.OrdinalIgnoreCase)) { list.Add(text); } } if (list.Count == 0) { Log.Warning($"Portal network {id}: the allow list could not be parsed; the network is open to everyone."); } return list; } 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) { if (TryGetDefinition(id, out var definition)) { displayName = definition.Name; return true; } displayName = null; return false; } internal static bool TryGetDefinition(long id, out PortalNetworkDefinition definition) { lock (ActiveById) { return ActiveById.TryGetValue(id, out definition); } } internal static List<long> GetSortedActiveIds() { lock (ActiveById) { return ActiveById.Keys.OrderBy((long k) => k).ToList(); } } internal static List<long> GetVisibleSortedActiveIds() { if (IsLocalPlayerNetworkPrivileged()) { return GetSortedActiveIds(); } string userId = NetPeerUtility.GetLocalUserId(); string numericId = NetPeerUtility.GetLocalPlayerIdString(); lock (ActiveById) { return (from kv in ActiveById where kv.Value == null || kv.Value.Allows(userId, numericId) select kv.Key into k orderby k select k).ToList(); } } internal static bool IsPlayerAllowed(long id, string userId, string numericPlayerId, bool privileged = false) { if (!IsReservedIdRange(id)) { return true; } if (privileged) { return true; } PortalNetworkDefinition value; lock (ActiveById) { ActiveById.TryGetValue(id, out value); } return value?.Allows(userId, numericPlayerId) ?? false; } internal static bool IsLocalPlayerAllowed(long id) { if (!IsReservedIdRange(id)) { return true; } PortalNetworkDefinition value; lock (ActiveById) { ActiveById.TryGetValue(id, out value); } if (value == null) { return false; } if (value.IsOpen || IsLocalPlayerNetworkPrivileged()) { return true; } return value.Allows(NetPeerUtility.GetLocalUserId(), NetPeerUtility.GetLocalPlayerIdString()); } internal static bool IsLocalPlayerNetworkPrivileged() { if (AdminsBypassNetworks) { return XPortalNetworksAdminSync.IsLocalPortalNetworkAdmin(); } return false; } 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) { ImportLegacyJsonIfNeeded(); RebuildFromConfig(); } } private static void ImportLegacyJsonIfNeeded() { try { XPortalNetworksConfig instance = XPortalNetworksConfig.Instance; if (!instance.HasAnyNetworkDefined() && TryReadConfigFile(out var text, out var _) && !string.IsNullOrWhiteSpace(text)) { Dictionary<long, PortalNetworkDefinition> dictionary = ParseConfigJson(text); if (dictionary.Count != 0) { instance.ApplyImportedNetworks(dictionary.Values); Log.Info(string.Format("Imported {0} portal network(s) from the legacy `{1}`. They are now ", dictionary.Count, "xportal_networks.json") + "managed in the config (`Portal Network 1`, `Portal Network 2`, ...) and the JSON file is no longer used - you can delete it."); } } } catch (Exception ex) { Log.Error("Legacy portal network import failed: " + ex.GetType().Name + ": " + ex.Message); } } private static string GetConfigFilePath() { string text = Path.Combine(Paths.ConfigPath, "XPortalNetworksTribesPins", "xportal_networks.json"); if (File.Exists(text)) { return text; } string text2 = Path.Combine(Paths.ConfigPath, "XPortalNetworks", "xportal_networks.json"); if (!File.Exists(text2)) { return text; } return text2; } 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, PortalNetworkDefinition> ParseConfigJson(string raw) { Dictionary<long, PortalNetworkDefinition> dictionary = new Dictionary<long, PortalNetworkDefinition>(); if (string.IsNullOrWhiteSpace(raw)) { return dictionary; } raw = StripUtf8Bom(raw.Trim()); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; try { foreach (Match item in NetworkObjectRegex.Matches(raw)) { string value = item.Value; Match match = NetworkIdRegex.Match(value); if (!match.Success || !int.TryParse(match.Groups[1].Value, out var result) || result < 1 || result > 15) { num++; continue; } Match match2 = NetworkNameRegex.Match(value); if (!match2.Success) { num2++; continue; } string text; try { text = UnescapeJsonString(match2.Groups[1].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 num6 = result; if (dictionary.ContainsKey(num6)) { num3++; continue; } List<string> list = ParseAllowList(value, result); if (list.Count > 0) { num5++; } dictionary.Add(num6, new PortalNetworkDefinition(num6, text, list)); } } 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 (num4 > 0) { Log.Warning(string.Format("Custom networks JSON: skipped {0} {1} with undecodable text.", num4, (num4 == 1) ? "entry" : "entries")); } if (num5 > 0) { Log.Debug(string.Format("Custom networks JSON: {0} {1} restricted by an allow list.", num5, (num5 == 1) ? "network is" : "networks are")); } if (dictionary.Count == 0 && raw.Length > 2) { Log.Warning(string.Format("Custom networks JSON: no valid entries found in `{0}`. Expected objects like \"id\": 1, \"name\": \"...\" (optionally with \"allow_list\": [\"...\"]) with ids in {1}–{2}. Check the file format.", "xportal_networks.json", 1, 15)); } return dictionary; } private static List<string> ParseAllowList(string body, int id) { List<string> list = new List<string>(); Match match = NetworkAllowListRegex.Match(body); if (!match.Success) { return list; } foreach (Match item in JsonStringRegex.Matches(match.Groups[1].Value)) { string raw; try { raw = UnescapeJsonString(item.Groups[1].Value); } catch (Exception ex) { Log.Warning($"Custom networks JSON: skipped an allow_list entry for id {id} (invalid escape sequence): {ex.GetType().Name}: {ex.Message}"); continue; } raw = PortalNetwork.SanitizeNetworkOwnerDisplayName(raw); if (!string.IsNullOrEmpty(raw) && !list.Contains<string>(raw, StringComparer.OrdinalIgnoreCase)) { list.Add(raw); } } return list; } 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); } } } 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) if (!knownPortals.TryGetValue(id, out var value)) { return null; } return value; } 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_0040: 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; } PortalMapPins.MarkDirty(); return knownPortals[portal.Id]; } public bool Remove(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) bool num = knownPortals.Remove(id); if (num) { PortalMapPins.MarkDirty(); } return num; } 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) 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 = ZdoTools.GetPreviousId(zdo), Target = ZdoTools.GetTarget(zdo), 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_013e: 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); } HashSet<ZDOID> updatedIds = new HashSet<ZDOID>(updatedPortals.Select((KnownPortal p) => p.Id)); List<KnownPortal> list = (from p in GetList() where !updatedIds.Contains(p.Id) select p).ToList(); Log.Debug($"Removing {list.Count} portals"); foreach (KnownPortal item in list) { Remove(item); } List<KnownPortal> list2 = (from p in GetList() where p.Target != ZDOID.None && !ContainsId(p.Target) select p).ToList(); Log.Debug($"Retargeting {list2.Count} portals"); foreach (KnownPortal item2 in list2) { 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(); PortalMapPins.MarkDirty(); } 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_0097: 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) || Game.instance.GetPlayerProfile() == 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; } if (peer.m_socket != null) { return ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } return false; } internal static long GetLocalPlayerId() { if ((Object)(object)Player.m_localPlayer != (Object)null) { return Player.m_localPlayer.GetPlayerID(); } if ((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile() != null) { return Game.instance.GetPlayerProfile().GetPlayerID(); } return 0L; } internal static string GetLocalUserId() { try { UserInfo localUser = UserInfo.GetLocalUser(); if (localUser != null && ((PlatformUserID)(ref localUser.UserId)).IsValid) { return ((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref localUser.UserId)/*cast due to .constrained prefix*/).ToString(); } } catch { } return string.Empty; } internal static string GetLocalPlayerIdString() { long localPlayerId = GetLocalPlayerId(); if (localPlayerId == 0L) { return string.Empty; } return localPlayerId.ToString(); } internal unsafe static string GetPeerUserId(long peerId) { //IL_006e: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null) { return string.Empty; } try { ZNetPeer peer = ZNet.instance.GetPeer(peerId); if (peer == null) { if (ZNet.instance.IsServer() && peerId == ZNet.GetUID()) { return GetLocalUserId(); } return string.Empty; } if (!((ZDOID)(ref peer.m_characterID)).IsNone()) { foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { if (!(player.m_characterID != peer.m_characterID)) { PlatformUserID id = player.m_userInfo.m_id; if (((PlatformUserID)(ref id)).IsValid) { id = player.m_userInfo.m_id; return ((object)(*(PlatformUserID*)(&id))/*cast due to .constrained prefix*/).ToString(); } } } } if (peer.m_socket != null) { string hostName = peer.m_socket.GetHostName(); if (!string.IsNullOrWhiteSpace(hostName)) { return hostName; } } } catch { } return string.Empty; } internal static string GetPeerPlayerIdString(long peerId) { long peerPlayerId = GetPeerPlayerId(peerId); if (peerPlayerId == 0L) { return string.Empty; } return peerPlayerId.ToString(); } } 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 PortalMapPins { private const float RefreshIntervalSeconds = 5f; private static readonly Dictionary<ZDOID, PinData> managedPins = new Dictionary<ZDOID, PinData>(); private static Minimap installedMinimap; private static PinType portalPinType; private static Sprite portalPinSprite; private static readonly Color PortalPinColour = new Color(0.196f, 0.804f, 0.196f, 1f); private static bool pinTypeInstalled; private static bool refreshQueued = true; private static float nextRefreshTime; internal static void MarkDirty() { refreshQueued = true; } internal static void Reset() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) try { if (!Environment.IsHeadless && (Object)(object)Minimap.instance != (Object)null) { RemoveAllPins(Minimap.instance); } } catch (Exception ex) { Log.Debug("Could not remove the portal map pins: " + ex.Message); } managedPins.Clear(); installedMinimap = null; portalPinType = (PinType)0; pinTypeInstalled = false; refreshQueued = true; nextRefreshTime = 0f; } internal static void Tick() { if (Environment.IsHeadless) { return; } Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null)) { float unscaledTime = Time.unscaledTime; if (refreshQueued || !(unscaledTime < nextRefreshTime)) { refreshQueued = false; nextRefreshTime = unscaledTime + 5f; Refresh(instance); } } } private static void Refresh(Minimap minimap) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) try { if (installedMinimap != minimap) { managedPins.Clear(); installedMinimap = minimap; pinTypeInstalled = false; portalPinType = (PinType)0; } if (!ShouldShowPins()) { RemoveAllPins(minimap); } else if (EnsurePortalPinType(minimap)) { Reconcile(minimap); } } catch (Exception ex) { Log.Warning("Could not update the portal map pins: " + ex.GetType().Name + ": " + ex.Message); } } private static bool ShouldShowPins() { XPortalNetworksConfig.ConfigSettings local = XPortalNetworksConfig.Instance.Local; if (local.ShowPortalPins.Value) { return !local.PingMapDisabled; } return false; } private static void Reconcile(Minimap minimap) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) long localPlayerId = NetPeerUtility.GetLocalPlayerId(); Dictionary<ZDOID, string> dictionary = new Dictionary<ZDOID, string>(); foreach (KnownPortal item in KnownPortalsManager.Instance.GetList()) { if (IsVisibleToLocalPlayer(item, localPlayerId)) { dictionary[item.Id] = GetPinName(item); } } foreach (ZDOID item2 in new List<ZDOID>(managedPins.Keys)) { if (!dictionary.TryGetValue(item2, out var value) || !IsStillOnMap(minimap, item2)) { DropPin(minimap, item2); continue; } KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(item2); PinData val = managedPins[item2]; if (knownPortalById == null || val == null || val.m_name != value || val.m_type != portalPinType || (Object)(object)val.m_icon != (Object)(object)portalPinSprite || !IsAt(val, knownPortalById.Location)) { DropPin(minimap, item2); } } foreach (KeyValuePair<ZDOID, string> item3 in dictionary) { if (managedPins.ContainsKey(item3.Key)) { continue; } KnownPortal knownPortalById2 = KnownPortalsManager.Instance.GetKnownPortalById(item3.Key); if (knownPortalById2 != null) { PinData val2 = minimap.AddPin(knownPortalById2.Location, portalPinType, item3.Value, false, false, 0L, default(PlatformUserID)); if (val2 != null) { ApplyPinAppearance(val2); managedPins[item3.Key] = val2; } } } } private static bool IsVisibleToLocalPlayer(KnownPortal portal, long localPlayerId) { if (portal == null) { return false; } long networkOwnerPlayerId = portal.NetworkOwnerPlayerId; if (CustomNetworks.IsReservedIdRange(networkOwnerPlayerId)) { if (!portal.IsPrivate) { return CustomNetworks.IsLocalPlayerAllowed(networkOwnerPlayerId); } return false; } if (portal.IsPrivate) { if (localPlayerId != 0L) { return networkOwnerPlayerId == localPlayerId; } return false; } return true; } private static string GetPinName(KnownPortal portal) { string friendlyName = portal.GetFriendlyName(); if (!XPortalNetworksConfig.Instance.Local.ShowNetworkInPinName.Value || !CustomNetworks.IsReservedIdRange(portal.NetworkOwnerPlayerId) || !CustomNetworks.TryGetDisplayName(portal.NetworkOwnerPlayerId, out var displayName) || string.IsNullOrWhiteSpace(displayName)) { return friendlyName; } return "[" + displayName + "] " + friendlyName; } private static bool IsStillOnMap(Minimap minimap, ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!managedPins.TryGetValue(id, out var value) || value == null) { return false; } return minimap.m_pins?.Contains(value) ?? false; } private static bool IsAt(PinData pin, Vector3 location) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = pin.m_pos - location; return ((Vector3)(ref val)).sqrMagnitude < 0.01f; } private static void DropPin(Minimap minimap, ZDOID id) { //IL_0005: 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) if (managedPins.TryGetValue(id, out var value)) { managedPins.Remove(id); List<PinData> pins = minimap.m_pins; if (value != null && pins != null && pins.Contains(value)) { minimap.RemovePin(value); } } } private static void RemoveAllPins(Minimap minimap) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) foreach (ZDOID item in new List<ZDOID>(managedPins.Keys)) { DropPin(minimap, item); } } private static bool EnsurePortalPinType(Minimap minimap) { //IL_005c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) List<SpriteData> icons = minimap.m_icons; if (icons == null) { return false; } if (!pinTypeInstalled || !icons.Exists(IsOurSpriteData)) { Sprite val = ResolvePortalPinSprite(minimap); if ((Object)(object)val == (Object)null) { return false; } portalPinType = (PinType)Enum.GetValues(typeof(PinType)).Length; icons.RemoveAll((SpriteData entry) => entry.m_name == portalPinType); icons.Add(new SpriteData { m_name = portalPinType, m_icon = val }); pinTypeInstalled = true; } EnsurePinTypeVisible(minimap); return true; } private static bool IsOurSpriteData(SpriteData entry) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (entry.m_name == portalPinType) { return (Object)(object)entry.m_icon == (Object)(object)portalPinSprite; } return false; } private static void EnsurePinTypeVisible(Minimap minimap) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected I4, but got Unknown int num = (int)portalPinType; bool[] visibleIconTypes = minimap.m_visibleIconTypes; if (visibleIconTypes != null && visibleIconTypes.Length > num) { visibleIconTypes[num] = true; return; } bool[] array = new bool[num + 1]; if (visibleIconTypes != null) { Array.Copy(visibleIconTypes, array, visibleIconTypes.Length); } for (int i = ((visibleIconTypes != null) ? visibleIconTypes.Length : 0); i < array.Length; i++) { array[i] = true; } minimap.m_visibleIconTypes = array; } private static void ApplyPinAppearance(PinData pin) { if (pin != null) { pin.m_icon = portalPinSprite; Image iconElement = pin.m_iconElement; if ((Object)(object)iconElement != (Object)null) { iconElement.sprite = portalPinSprite; } ApplyColour(pin); } } private static void ApplyColour(PinData pin) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) Image val = pin?.m_iconElement; if ((Object)(object)val != (Object)null) { ((Graphic)val).color = PortalPinColour; } } internal static void ReapplyColours() { if (Environment.IsHeadless || managedPins.Count == 0) { return; } foreach (PinData value in managedPins.Values) { ApplyColour(value); } } private static Sprite ResolvePortalPinSprite(Minimap minimap) { if ((Object)(object)portalPinSprite != (Object)null) { return portalPinSprite; } List<SpriteData> icons = minimap.m_icons; Sprite val = FindPortalIcon(icons); if ((Object)(object)val != (Object)null) { Log.Debug("Portal map pins use the game's `" + ((Object)val).name + "` icon."); portalPinSprite = val; return portalPinSprite; } Log.Warning("No portal icon was found in the minimap icon list; the portal map pins fall back to a generated marker."); Log.Debug("Minimap icon list: " + DescribeIcons(icons)); portalPinSprite = CreateFallbackPortalIcon(); return portalPinSprite; } private static Sprite FindPortalIcon(List<SpriteData> icons) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (icons == null) { return null; } foreach (SpriteData icon2 in icons) { Sprite icon = icon2.m_icon; if ((Object)(object)icon != (Object)null && ((Object)icon).name != null && ((Object)icon).name.IndexOf("portal", StringComparison.OrdinalIgnoreCase) >= 0) { return icon; } } return null; } private static string DescribeIcons(List<SpriteData> icons) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (icons == null) { return "the icon list is unavailable"; } List<string> list = new List<string>(); foreach (SpriteData icon in icons) { list.Add(((Object)(object)icon.m_icon != (Object)null && ((Object)icon.m_icon).name != null) ? ((Object)icon.m_icon).name : "<unnamed>"); } return string.Format("{0} icons: {1}", list.Count, string.Join(", ", list)); } private static Sprite CreateFallbackPortalIcon() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(15.5f, 15.5f); Texture2D val2 = new Texture2D(32, 32, (TextureFormat)4, false); ((Object)val2).name = "XPortalNetworks_PortalIcon"; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).filterMode = (FilterMode)1; Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < array.Length; i++) { Vector2 val3 = new Vector2((float)(i % 32), (float)(i / 32)) - val; float num = Mathf.Abs(((Vector2)(ref val3)).magnitude - 9.5f); array[i] = new Color(1f, 1f, 1f, Mathf.Clamp01((0.9f - num) * 4f)); } val2.SetPixels(array); val2.Apply(true, false); return Sprite.Create(val2, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 32f); } } 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 RestrictPortalRemovalToCreator; public bool RestrictPortalRemovalToUsable; public bool AdminsSeeAllNetworks; public ConfigEntry<string>[] NetworkNames = new ConfigEntry<string>[16]; public ConfigEntry<string>[] NetworkAllowLists = new ConfigEntry<string>[16]; public ConfigEntry<bool> ShowPortalPins; public ConfigEntry<bool> ShowNetworkInPinName; } private static readonly Lazy<XPortalNetworksConfig> lazy = new Lazy<XPortalNetworksConfig>(() => new XPortalNetworksConfig()); private const string Desc_EnforcedByServer = " This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host)."; private ConfigFile configFile; public static XPortalNetworksConfig Instance => lazy.Value; public ConfigSettings Local { get; set; } public event Action OnLocalConfigChanged; private XPortalNetworksConfig() { Local = new ConfigSettings(); } public void LoadLocalConfig(ConfigFile configFile) { this.configFile = configFile; ReloadLocalConfig(); this.configFile.ConfigReloaded += LocalConfigChanged; this.configFile.SettingChanged += LocalConfigChanged; } public void MigrateLegacyConfigFile(ConfigFile configFile) { this.configFile = configFile; string text = ((configFile != null) ? configFile.ConfigFilePath : null); if (string.IsNullOrEmpty(text)) { return; } string text2 = Path.Combine(Paths.ConfigPath, "vapok.mods.xportalnetworks.cfg"); if (!File.Exists(text2) || HasSettings(text)) { return; } try { File.Copy(text2, text, overwrite: true); configFile.Reload(); Log.Info("Migrated the legacy config file `" + Path.GetFileName(text2) + "` to `" + Path.GetFileName(text) + "`. The old file is no longer read and can be deleted."); } catch (Exception ex) { Log.Error("Could not migrate the legacy config file `" + text2 + "`: " + ex.GetType().Name + ": " + ex.Message + ". Settings start from their defaults - copy that file to `" + text + "` yourself to keep them."); } } private static bool HasSettings(string configFilePath) { if (!File.Exists(configFilePath)) { return false; } return File.ReadAllText(configFilePath).TrimStart(new char[1] { '\ufeff' }).Trim() .Length > 0; } private void ReloadLocalConfig() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Expected O, but got Unknown //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Expected O, but got Unknown //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Expected O, but got Unknown //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Expected O, but got Unknown //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Expected O, but got Unknown //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Expected O, but got Unknown //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Expected O, but got Unknown ConfigEntry<bool> val = configFile.Bind<bool>("General", "PingMapDisabled", false, new ConfigDescription("Disable the Ping Map button completely. For players who wish to play without a map. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); 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, new ConfigDescription("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 owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); 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, new ConfigDescription("In the list of portals, do not show how far away other portals are. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); Local.HidePortalDistance = val4.Value; bool? flag = MigrateRenamedBool("General", "RestrictPortalRemoval", "RestrictPortalRemovalToCreator"); if (flag.HasValue) { Log.Info($"Renamed the `General/RestrictPortalRemoval` setting to `General/RestrictPortalRemovalToCreator` (value {flag.Value}). The old key is no longer read and can be deleted."); } ConfigEntry<bool> val5 = configFile.Bind<bool>("General", "RestrictPortalRemovalToCreator", flag ?? true, new ConfigDescription("When true, only the player who placed the portal may remove it with the hammer - or a server admin/host while AdminsSeeAllNetworks lets admins bypass portal networks. When RestrictPortalRemovalToUsable is also enabled, both rules have to be satisfied. Other removal (e.g. structural damage) is unchanged. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); Local.RestrictPortalRemovalToCreator = val5.Value; ConfigEntry<bool> val6 = configFile.Bind<bool>("General", "RestrictPortalRemovalToUsable", true, new ConfigDescription("When true, a player may only remove a portal with the hammer if they are allowed to use it: portals on the Global network, on an unrestricted network, or on a network they are a member of, plus their own private portals. Admins and the host are treated like normal players here unless AdminsSeeAllNetworks lets them bypass portal networks. When RestrictPortalRemovalToCreator is also enabled, both rules have to be satisfied - a player may then only remove a portal they placed and may still use. Other removal (e.g. structural damage) is unchanged. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); Local.RestrictPortalRemovalToUsable = val6.Value; ConfigEntry<bool> val7 = configFile.Bind<bool>("General", "AdminsSeeAllNetworks", false, new ConfigDescription("When true, server admins (and the host) can see and use every portal network, bypassing allow lists. When false, admins are treated like normal players and only see/use unrestricted networks or networks they are members of. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); Local.AdminsSeeAllNetworks = val7.Value; for (int i = 1; i <= 15; i++) { Local.NetworkNames[i] = configFile.Bind<string>($"Portal Network {i}", "Name", string.Empty, new ConfigDescription($"Display name of portal network {i}. Leave empty to keep this network unused." + " This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 2 } })); Local.NetworkAllowLists[i] = configFile.Bind<string>($"Portal Network {i}", "Permitted", string.Empty, new ConfigDescription($"Comma separated player ids allowed to use portal network {i} (e.g. Steam_12345678901234567). " + "Leave empty to let everyone use it; ignored while the network has no name. This setting is owned by the server: it is synchronized from the server to all clients and can only be changed by server admins (or the host).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = 1 } })); } MigrateLegacyNetworkSections(); Local.ShowPortalPins = configFile.Bind<bool>("Local Config", "Show Portal Map Pins", true, new ConfigDescription("If enabled, the portals you are allowed to use are shown as pins on your own map. Only portals on networks you can access, plus your own private portals, are pinned - other players' private portals never are. This is a local preference; no portal pins are shown while the server has PingMapDisabled enabled.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 2 } })); Local.ShowNetworkInPinName = configFile.Bind<bool>("Local Config", "Show Network In Pin Name", false, new ConfigDescription("If enabled, the map pin of a portal is prefixed with the name of the portal network it is on, for example \"[Trade Hub] North Base\". This is a local preference.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 1 } })); } private bool? MigrateRenamedBool(string section, string oldKey, string newKey) { ConfigFile obj = configFile; string text = ((obj != null) ? obj.ConfigFilePath : null); if (string.IsNullOrEmpty(text) || !File.Exists(text)) { return null; } try { bool flag = false; bool? result = null; string[] array = File.ReadAllLines(text); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2[0] == '#') { continue; } if (text2[0] == '[') { flag = text2.Equals("[" + section + "]", StringComparison.OrdinalIgnoreCase); } else { if (!flag) { continue; } int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string value = text2.Substring(num + 1).Trim(); if (text3.Equals(newKey, StringComparison.OrdinalIgnoreCase)) { return null; } if (text3.Equals(oldKey, StringComparison.OrdinalIgnoreCase) && bool.TryParse(value, out var result2)) { result = result2; } } } } return result; } catch (Exception ex) { Log.Warning("Could not read the renamed `" + section + "/" + oldKey + "` setting from the config file: " + ex.Message); return null; } } private void MigrateLegacyNetworkSections() { ConfigFile obj = configFile; string text = ((obj != null) ? obj.ConfigFilePath : null); if (string.IsNullOrEmpty(text) || !File.Exists(text)) { return; } Dictionary<long, (string, string)> dictionary; try { string text2 = File.ReadAllText(text); if (text2.IndexOf("Portal Networks", StringComparison.OrdinalIgnoreCase) < 0) { return; } dictionary = ParseLegacyNetworkSection(text2); } catch (Exception ex) { Log.Warning("Could not read the legacy portal networks from the config file: " + ex.Message); return; } if (dictionary.Count == 0) { return; } int num = 0; foreach (KeyValuePair<long, (string, string)> item in dictionary) { int num2 = (int)item.Key; num += AssignIfEmpty(Local.NetworkNames[num2], item.Value.Item1); num += AssignIfEmpty(Local.NetworkAllowLists[num2], item.Value.Item2); } if (num == 0) { return; } try { configFile.Save(); Log.Info($"Migrated {num} legacy portal-network setting(s) from the old `[Portal Networks]` section into the per-network config sections."); } catch (Exception ex2) { Log.Warning("Could not save the config after migrating the portal networks: " + ex2.Message); } } private static int AssignIfEmpty(ConfigEntry<string> target, string value) { if (target == null || string.IsNullOrWhiteSpace(value) || !string.IsNullOrWhiteSpace(target.Value)) { return 0; } target.Value = value; return 1; } private static Dictionary<long, (string Name, string Permitted)> ParseLegacyNetworkSection(string text) { Dictionary<long, (string, string)> dictionary = new Dictionary<long, (string, string)>(); bool flag = false; string[] array = text.Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2[0] == '#') { continue; } if (text2[0] == '[') { flag = text2.Equals("[Portal Networks]", StringComparison.OrdinalIgnoreCase); } else { if (!flag) { continue; } int num = text2.IndexOf('='); if (num <= 0) { continue; } string input = text2.Substring(0, num).Trim(); string text3 = text2.Substring(num + 1).Trim(); if (text3.Length != 0) { Match match = Regex.Match(input, "^Network\\s+(\\d+)\\s+(Name|Allow List)$", RegexOptions.IgnoreCase); if (match.Success && int.TryParse(match.Groups[1].Value, out var result) && result >= 1 && result <= 15) { dictionary.TryGetValue(result, out var value); dictionary[result] = (match.Groups[2].Value.Equals("Name", StringComparison.OrdinalIgnoreCase) ? (text3, value.Item2) : (value.Item1, text3)); } } } } return dictionary; } internal string GetNetworkName(int id) { if (id < 1 || id > 15) { return string.Empty; } return Local.NetworkNames[id]?.Value ?? string.Empty; } internal string GetNetworkAllowList(int id) { if (id < 1 || id > 15) { return string.Empty; } return Local.NetworkAllowLists[id]?.Value ?? string.Empty; } internal bool HasAnyNetworkDefined() { for (int i = 1; i <= 15; i++) { if (!string.IsNullOrWhiteSpace(GetNetworkName(i))) { return true; } } return false; } internal void ApplyImportedNetworks(IEnumerable<CustomNetworks.PortalNetworkDefinition> definitions) { bool flag = false; foreach (CustomNetworks.PortalNetworkDefinition definition in definitions) { int num = (int)definition.Id; if (num >= 1 && num <= 15) { ConfigEntry<string> val = Local.NetworkNames[num]; if (val != null && string.IsNullOrWhiteSpace(val.Value) && !string.IsNullOrWhiteSpace(definition.Name)) { val.Value = definition.Name; flag = true; } ConfigEntry<string> val2 = Local.NetworkAllowLists[num]; if (val2 != null && string.IsNullOrWhiteSpace(val2.Value) && definition.AllowList.Count > 0) { val2.Value = string.Join(", ", definition.AllowList); flag = true; } } } if (!flag) { return; } try { ConfigFile obj = configFile; if (obj != null) { obj.Save(); } } catch (Exception ex) { Log.Warning("Could not save the config after importing the legacy portal networks: " + ex.Message); } } private void LocalConfigChanged(object sender, EventArgs e) { ReloadLocalConfig(); Log.Debug("The config was changed, rebuilding the portal network list.."); CustomNetworks.RebuildFromConfig(); this.OnLocalConfigChanged?.Invoke(); } } public class KnownPortal : IEquatable<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_0032: Unknown result type (might be due to invalid IL or missing references) if (!HasTarget()) { return Localization.instance.Localize("$piece_portal_target_none"); } KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(Target); if (knownPortalById == null) { return $"{Target} (invalid)"; } return knownPortalById.GetFriendlyName(); } public bool HasTarget() { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) 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; } public bool Equals(KnownPortal other) { //IL_000c: 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) if (other == null) { return false; } if (this == other) { return true; } return Id == other.Id; } public override bool Equals(object obj) { return Equals(obj as KnownPortal); } public override int GetHashCode() { //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 ((object)Id/*cast due to .constrained prefix*/).GetHashCode(); } } [BepInPlugin("ghostwheel.mods.xportalnetworkstribespins", "XPortalNetworksTribesPins", "3.1.1")] [BepInIncompatibility("com.sweetgiorni.anyportal")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class XPortalNetworks : BaseUnityPlugin { public const string Key_TargetId = "XPortalNetworksTribesPins_TargetId"; public const string Key_PreviousId = "XPortalNetworksTribesPins_PreviousId"; public const string Key_NetworkOwnerPlayerId = "XPortalNetworksTribesPins_NetworkOwnerPlayerId"; public const string Key_NetworkOwnerDisplayName = "XPortalNetworksTribesPins_NetworkOwnerDisplayName"; public const string Key_IsPrivate = "XPortalNetworksTribesPins_IsPrivate"; public const string LegacyKey_TargetId = "XPortalNetworks_TargetId"; public const string LegacyKey_PreviousId = "XPortalNetworks_PreviousId"; public const string LegacyKey_NetworkOwnerPlayerId = "XPortalNetworks_NetworkOwnerPlayerId"; public const string LegacyKey_NetworkOwnerDisplayName = "XPortalNetworks_NetworkOwnerDisplayName"; public const string LegacyKey_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.MigrateLegacyConfigFile(((BaseUnityPlugin)this).Config); XPortalNetworksConfig.Instance.LoadLocalConfig(((BaseUnityPlugin)this).Config); XPortalNetworksConfig.Instance.OnLocalConfigChanged += OnLocalConfigChanged; CustomNetworks.ListChanged += OnNetworksListChanged; if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance.AddInputs(); } MinimapManager.OnVanillaMapDataLoaded += MinimapManager_OnVanillaMapDataLoaded; Patcher.Patch(); } private void Update() { QueuedAction.Update(); PortalMapPins.Tick(); 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(); PortalMapPins.Reset(); if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance?.Dispose(); } KnownPortalsManager.Instance?.Dispose(); } private static void MinimapManager_OnVanillaMapDataLoaded() { long sessionID = ZDOMan.GetSessionID(); string arg = (((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile() != null) ? Game.instance.GetPlayerProfile().GetName() : "Player"); SendToServer.SyncRequest($"{arg} ({sessionID}) has joined the game"); } private static void UpdatePortalRecipe() { if ((Object)(object)ObjectDB.instance == (Object)null) { Log.Error("ObjectDB not instantiated"); return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { Log.Error("Could not find Hammer prefab"); } else { if (val.m_itemData?.m_shared?.m_buildPieces?.m_pieces == null) { return; } Piece val2 = (from go in val.m_itemData.m_shared.m_buildPieces.m_pieces where (Object)(object)go != (Object)null && ((Object)go).name.Equals("portal_wood") select go.GetComponent<Piece>()).FirstOrDefault(); if ((Object)(object)val2 == (Object)null || val2.m_resources == null) { return; } BackUpPortalRecipe(val2.m_resources); Requirement[] resources = val2.m_resources; foreach (Requirement val3 in resources) { if (val3 == null || (Object)(object)val3.m_resItem == (Object)null) { continue; } string name = ((Object)val3.m_resItem).name; if (portalRecipeOriginal.TryGetValue(name, out var value)) { int num2 = value; if (XPortalNetworksConfig.Instance.Local.DoublePortalCosts) { num2 = 2 * value; Log.Debug($"Doubling amount for requirement {((Object)val3.m_resItem).name} for item {((Object)val2).name} from {value} to {num2}"); } else if (portalRecipeAltered) { Log.Debug($"Resetting amount for requirement {((Object)val3.m_resItem).name} for item {((Object)val2).name} to {num2}"); } val3.m_amount = num2; } } portalRecipeAltered = XPortalNetworksConfig.Instance.Local.DoublePortalCosts; } } private static void BackUpPortalRecipe(Requirement[] requirements) { if (portalRecipeOriginal != null && portalRecipeOriginal.Count > 0) { return; } Log.Debug("Copying original requirements for portal recipe"); portalRecipeOriginal = new Dictionary<string, int>(); foreach (Requirement val in requirements) { if (val != null && (Object)(object)val.m_resItem != (Object)null) { portalRecipeOriginal.Add(((Object)val.m_resItem).name, val.m_amount); } } } private static void OnNetworksListChanged() { PortalMapPins.MarkDirty(); if (!Environment.IsHeadless) { PortalConfigurationPanel.Instance.OnNetworksListChanged(); } } internal static void OnLocalConfigChanged() { UpdatePortalRecipe(); PortalMapPins.MarkDirty(); } internal static void GameStarted() { KnownPortalsManager.Instance.Reset(); XPortalNetworksAdminSync.ResetForNewSession(); CustomNetworks.ResetSession(); PortalMapPins.Reset(); 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!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); if (knownPortalById == null) { result = string.Empty; return; } if (IsPortalHiddenFromLocalPlayer(knownPortalById)) { result = Localization.instance.Localize("$hud_xportal_network_restricted"); return; } string friendlyName = knownPortalById.GetFriendlyName(); string friendlyTargetName = knownPortalById.GetFriendlyTargetName(); string text = string.Empty; if (knownPortalById.HasTarget()) { ZDOID target = knownPortalById.Target; KnownPortal knownPortalById2 = KnownPortalsManager.Instance.GetKnownPortalById(target); if (knownPortalById2 == null) { 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) { 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_005b: Unknown result type (might be due to invalid IL or missing references) ZDOID uid = teleportWorld.m_nview.GetZDO().m_uid; KnownPortal knownPortalById = KnownPortalsManager.Instance.GetKnownPortalById(uid); if (knownPortalById == null) { Log.Error("Interacting with an unknown portal"); return; } Log.Debug($"Interacting with: {knownPortalById}"); Piece component = ((Component)teleportWorld).GetComponent<Piece>(); bool flag = XPortalNetworksAdminSync.IsLocalPortalNetworkAdmin(); if (!CustomNetworks.IsLocalPlayerAllowed(knownPortalById.NetworkOwnerPlayerId)) { Log.Debug($"Blocked configuration of portal `{knownPortalById.Id}` on restricted network `{knownPortalById.NetworkOwnerPlayerId}`"); ShowRestrictedNetworkMessage(); return; } bool num = (Object)(object)component != (Object)null && component.IsCreator(); bool canEditNetwork = num || flag; bool canEditPortalFully = num || flag; PortalConfigurationPanel.Instance.ConfigurePortal(knownPortalById, canEditNetwork, canEditPortalFully); } private static void ShowRestrictedNetworkMessage() { try { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, Localization.instance.Localize("$hud_xportal_network_restricted"), 0, (Sprite)null, false, true); } } catch (Exception ex) { Log.Warning("Could not show restricted network message: " + ex.Message); } } private static bool IsPortalHiddenFromLocalPlayer(KnownPortal portal) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (portal == null) { return false; } if (IsNetworkHiddenFromLocalPlayer(portal.NetworkOwnerPlayerId)) { return true; } if (portal.HasTarget() && KnownPortalsManager.Instance.TryGetValue(portal.Target, out var portal2)) { return IsNetworkHiddenFromLocalPlayer(portal2.NetworkOwnerPlayerId); } return false; } private static bool IsNetworkHiddenFromLocalPlayer(long networkId) { if (CustomNetworks.IsReservedIdRange(networkId)) { return !CustomNetworks.IsLocalPlayerAllowed(networkId); } return false; } internal static void OnPortalPlaced(ZDOID portalId, Vector3 location) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Log.Debug($"Portal `{portalId}` was placed"); if (ZDOMan.instance != null) { ZDOMan.instance.ForceSendZDO(portalId); } KnownPortal knownPortal = new KnownPortal(portalId, location); KnownPortalsManager.Instance.AddOrUpdate(knownPortal); ZdoTools.UpdateFromKnownPortal(delayed: false, knownPortal); SendToServer.AddOrUpdateRequest(knownPortal); } internal unsafe static void OnPortalDestroyed(ZDOID portalId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0050: Unknown result type (might be due to invalid IL or missing references) if (KnownPortalsManager.Instance.ContainsId(portalId)) { string text = KnownPortalsManager.Instance.GetKnownPortalById(portalId)?.Name ?? ((object)(*(ZDOID*)(&portalId))/*cast due to .constrained prefix*/).ToString(); Log.Debug("Portal `" + text + "` 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_001a: 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) if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } long playerID = Player.m_localPlayer.GetPlayerID(); if (!PrivateUseBlocked(sourcePortalId, playerID)) { return NetworkUseBlocked(sourcePortalId, playerID); } return true; } internal static bool NetworkUseBlocked(ZDOID sourcePortalId, long playerId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!KnownPortalsManager.Instance.TryGetValue(sourcePortalId, out var portal)) { return false; } if (NetworkRestrictedForPlayer(portal.NetworkOwnerPlayerId, playerId)) { return true; } if (portal.HasTarget() && KnownPortalsManager.Instance.TryGetValue(portal.Target, out var portal2)) { return NetworkRestrictedForPlayer(portal2.NetworkOwnerPlayerId, playerId); } return false; } private static bool NetworkRestrictedForPlayer(long networkId, long playerId) { if (!CustomNetworks.IsReservedIdRange(networkId)) { return false; } bool privileged = playerId != 0L && NetPeerUtility.GetLocalPlayerId() == playerId && CustomNetworks.AdminsBypassNetworks && XPortalNetworksAdminSync.IsLocalPortalNetworkAdmin(); return !CustomNetworks.IsPlayerAllowed(networkId, NetPeerUtility.GetLocalUserId(), (playerId != 0L) ? playerId.ToString() : string.Empty, privileged); } internal static bool IsUsablePortal(TeleportWorld portal, Player player, bool originalFlag) { //IL_004b: 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) 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; } long playerID = player.GetPlayerID(); return !PrivateUseBlocked(zDO.m_uid, playerID) && !NetworkUseBlocked(zDO.m_uid, playerID); } internal static List<ZDO> ProcessSyncRequest(string reason) { List<ZDO> allPortalZDOs = GetAllPortalZDOs(); Log.Debug($"Fetched {allPortalZDOs.Count} portals"); if (allPortalZDOs != null) { ForceLocalPortalUpdate(allPortalZDOs); } if (Environment.IsServer) { CustomNetworks.MigrateInvalidNetworks(); } SendToClient.Resync(KnownPortalsManager.Instance.Pack(), reason); return allPortalZDOs; } private static List<ZDO> GetAllPortalZDOs() { if (ZDOMan.instance == null) { return new List<ZDO>(); } 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_019d: 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 = 0L;