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 VikingsPortals v1.0.0
plugins/VikingsPortals.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Groups; using Guilds; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using VikingsAscensionAPI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: AssemblyTitle("VikingsPortals")] [assembly: AssemblyProduct("VikingsPortals")] [assembly: AssemblyInformationalVersion("1.0.0+15dbe340bdad566954a87d2bb37f562a4bc93a15")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCompany("VikingsPortals")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: <2dea9613-89dc-4972-ac37-d2600ff957a3>RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<9673c41f-ef17-4443-8b62-bb449451d413>Embedded] internal sealed class <9673c41f-ef17-4443-8b62-bb449451d413>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [<9673c41f-ef17-4443-8b62-bb449451d413>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <7a806118-b484-4911-b895-cee4047d3ab8>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <7a806118-b484-4911-b895-cee4047d3ab8>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <7a806118-b484-4911-b895-cee4047d3ab8>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<9673c41f-ef17-4443-8b62-bb449451d413>Embedded] [CompilerGenerated] internal sealed class <596d02bc-cb07-4f28-80d1-942233a59b21>NullableContextAttribute : Attribute { public readonly byte Flag; public <596d02bc-cb07-4f28-80d1-942233a59b21>NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<9673c41f-ef17-4443-8b62-bb449451d413>Embedded] internal sealed class <2dea9613-89dc-4972-ac37-d2600ff957a3>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <2dea9613-89dc-4972-ac37-d2600ff957a3>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalizationManager { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static BaseUnityPlugin _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] [method: <596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] [field: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] public static event Action OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (object _, EventArgs _) => { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' }); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static byte[] LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] public const string Version = "1.4.1"; } } namespace VikingsPortals { [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static class AscensionBridge { public static bool GuildsActive() { return ReadGuildsActive(); } public static int OwnGuildId() { return ReadOwnGuildId(); } public static int PlayerGuildId(string playerId, string playerName) { return (!string.IsNullOrEmpty(playerId)) ? ReadPlayerGuildId(playerId, playerName ?? "") : 0; } public static string GuildName(int id) { return (id == 0) ? "" : ReadGuildName(id); } [MethodImpl(MethodImplOptions.NoInlining)] private static bool ReadGuildsActive() { return AscensionAPI.AscensionIsGuildsActive(); } [MethodImpl(MethodImplOptions.NoInlining)] private static int ReadOwnGuildId() { return AscensionAPI.AscensionGetOwnGuildId(); } [MethodImpl(MethodImplOptions.NoInlining)] private static int ReadPlayerGuildId(string playerId, string playerName) { return AscensionAPI.AscensionGetPlayerGuildId(playerId, playerName); } [MethodImpl(MethodImplOptions.NoInlining)] private static string ReadGuildName(int id) { return AscensionAPI.AscensionGetGuildName(id) ?? ""; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class GroupsBridge { private const string PluginId = "org.bepinex.plugins.groups"; public static bool Loaded() { if (!Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.groups")) { return false; } try { return ApiLoaded(); } catch { return false; } } public static bool SameGroupAsOwner(string ownerId) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(ownerId) || !Loaded()) { return false; } if (!FindOnlinePlayer(ownerId, out var found)) { return false; } try { return GroupContains(found); } catch { return false; } } private unsafe static bool FindOnlinePlayer(string playerId, out PlayerInfo found) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) found = default(PlayerInfo); if ((Object)(object)ZNet.instance == (Object)null) { return false; } List<PlayerInfo> playerList = ZNet.instance.GetPlayerList(); if (playerList == null) { return false; } foreach (PlayerInfo item in playerList) { PlatformUserID id = item.m_userInfo.m_id; if (!string.Equals(((object)(*(PlatformUserID*)(&id))/*cast due to .constrained prefix*/).ToString(), playerId, StringComparison.Ordinal)) { continue; } found = item; return true; } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private static bool ApiLoaded() { return Groups.API.IsLoaded(); } [MethodImpl(MethodImplOptions.NoInlining)] private static bool GroupContains(PlayerInfo owner) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Groups.API.GroupPlayers()?.Contains(Groups.PlayerReference.fromPlayerInfo(owner)) ?? false; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class GuildBridge { public const int SourceNone = 0; public const int SourceGuilds = 1; public const int SourceAscension = 2; public static int ActiveSource() { if (AscensionBridge.GuildsActive()) { return 2; } if (GuildsBridge.Loaded()) { return 1; } return 0; } public static int OwnGuildId(int source) { return source switch { 2 => AscensionBridge.GuildsActive() ? AscensionBridge.OwnGuildId() : 0, 1 => GuildsBridge.OwnGuildId(), _ => 0, }; } public static int PlayerGuildId(int source, string playerId, string playerName) { return source switch { 2 => AscensionBridge.GuildsActive() ? AscensionBridge.PlayerGuildId(playerId, playerName) : 0, 1 => GuildsBridge.PlayerGuildId(playerId, playerName), _ => 0, }; } public static string GuildName(int source, int id) { if (id == 0) { return ""; } return source switch { 2 => AscensionBridge.GuildName(id), 1 => GuildsBridge.GuildName(id), _ => "", }; } public static bool LocalInGuild(ZDO zdo) { (int, int) tuple = PortalRecord.Guild(zdo); if (tuple.Item1 == 0 || tuple.Item2 == 0) { return false; } return OwnGuildId(tuple.Item2) == tuple.Item1; } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static class GuildsBridge { private const string PluginId = "org.bepinex.plugins.guilds"; public static bool Loaded() { if (!Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.guilds")) { return false; } try { return ApiLoaded(); } catch { return false; } } public static int OwnGuildId() { if (!Loaded()) { return 0; } try { return ReadOwnGuildId(); } catch { return 0; } } public static int PlayerGuildId(string playerId, string playerName) { if (string.IsNullOrEmpty(playerId) || !Loaded()) { return 0; } try { return ReadPlayerGuildId(playerId, playerName ?? ""); } catch { return 0; } } public static string GuildName(int id) { if (id == 0 || !Loaded()) { return ""; } try { return ReadGuildName(id); } catch { return ""; } } [MethodImpl(MethodImplOptions.NoInlining)] private static bool ApiLoaded() { return Guilds.API.IsLoaded(); } [MethodImpl(MethodImplOptions.NoInlining)] private static int ReadOwnGuildId() { return Guilds.API.GetOwnGuild()?.General.id ?? 0; } [MethodImpl(MethodImplOptions.NoInlining)] private static int ReadPlayerGuildId(string playerId, string playerName) { return Guilds.API.GetPlayerGuild(new Guilds.PlayerReference { id = playerId, name = playerName })?.General.id ?? 0; } [MethodImpl(MethodImplOptions.NoInlining)] private static string ReadGuildName(int id) { return Guilds.API.GetGuild(id)?.Name ?? ""; } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal readonly struct PortalFacts { public PortalMode Mode { get; } public string OwnerId { get; } public PortalFacts(PortalMode mode, string ownerId) { Mode = mode; OwnerId = ownerId; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal readonly struct ViewerFacts { public string Id { get; } public bool IsAdmin { get; } public ViewerFacts(string id, bool isAdmin) { Id = id; IsAdmin = isAdmin; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class AccessRules { public static bool IsOwner(PortalFacts p, ViewerFacts v) { return !string.IsNullOrEmpty(p.OwnerId) && string.Equals(p.OwnerId, v.Id, StringComparison.Ordinal); } public static bool CanUse(PortalFacts p, ViewerFacts v, Func<bool> sameGroup, Func<bool> sameGuild) { if (IsOwner(p, v) || v.IsAdmin) { return true; } return p.Mode switch { PortalMode.Public => true, PortalMode.Group => sameGroup(), PortalMode.Guild => sameGuild(), _ => false, }; } public static bool CanEdit(PortalFacts p, ViewerFacts v, bool adminBypass, bool groupAccess, bool guildAccess, Func<bool> sameGroup, Func<bool> sameGuild) { if (string.IsNullOrEmpty(p.OwnerId)) { return v.IsAdmin; } if (IsOwner(p, v)) { return true; } if (v.IsAdmin && adminBypass) { return true; } if (p.Mode == PortalMode.Group) { return groupAccess && sameGroup(); } if (p.Mode == PortalMode.Guild) { return guildAccess && sameGuild(); } return false; } public static bool CanChangeMode(PortalFacts p, ViewerFacts v) { return IsOwner(p, v) || v.IsAdmin; } } internal static class ModeColors { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public static Color Parse(string hex, Color fallback) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_00ab: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(hex)) { return fallback; } string text = hex.Trim(); if (text.StartsWith("#")) { text = text.Substring(1); } if (text.Length != 6 && text.Length != 8) { return fallback; } string text2 = text; foreach (char c in text2) { if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) { return fallback; } } byte b = byte.Parse(text.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); byte b2 = byte.Parse(text.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); byte b3 = byte.Parse(text.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); byte b4 = ((text.Length == 8) ? byte.Parse(text.Substring(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture) : byte.MaxValue); return new Color((float)(int)b / 255f, (float)(int)b2 / 255f, (float)(int)b3 / 255f, (float)(int)b4 / 255f); } public static Color Default(PortalMode mode) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_005d: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(1f, 1f, 1f, 1f); return (Color)(mode switch { PortalMode.Public => Parse("#FFC830", val), PortalMode.Private => Parse("#3DA5FF", val), PortalMode.Group => Parse("#40FF60", val), PortalMode.Guild => Parse("#B040FF", val), PortalMode.Admin => Parse("#FF4040", val), _ => val, }); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class FavoriteList { private const char Separator = ';'; public static HashSet<string> Read(string stored) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if (string.IsNullOrEmpty(stored)) { return hashSet; } string[] array = stored.Split(new char[1] { ';' }); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length > 0) { hashSet.Add(text2); } } return hashSet; } public static string Write(IEnumerable<string> keys) { if (keys == null) { return ""; } IOrderedEnumerable<string> values = (from k in keys where !string.IsNullOrEmpty(k) select k.Trim() into k where k.Length > 0 select k).Distinct<string>(StringComparer.Ordinal).OrderBy<string, string>([<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (string k) => k, StringComparer.Ordinal); return string.Join(';'.ToString(), values); } public static string Key(Vector3 position) { //IL_0009: 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_0035: Unknown result type (might be due to invalid IL or missing references) return Axis(position.x) + "," + Axis(position.y) + "," + Axis(position.z); } public static IReadOnlyList<T> Favorites<[<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] T>(IEnumerable<T> items, Func<T, string> name, Func<T, bool> isFavorite) { if (items == null) { return new List<T>(); } return items.Where(isFavorite).OrderBy<T, string>([<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (T item) => name(item) ?? "", StringComparer.InvariantCultureIgnoreCase).ThenBy<T, string>([<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (T item) => name(item) ?? "", StringComparer.Ordinal) .ToList(); } private static string Axis(float value) { double num = Math.Round(value, 1, MidpointRounding.AwayFromZero); if (num == 0.0) { num = 0.0; } return num.ToString("F1", CultureInfo.InvariantCulture); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class Identity { public static string Local { get { //IL_001b: 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) IDistributionPlatform distributionPlatform = PlatformManager.DistributionPlatform; ILocalUser val = ((distributionPlatform != null) ? distributionPlatform.LocalUser : null); string text = ((val != null) ? ((object)((IUser)val).PlatformUserID/*cast due to .constrained prefix*/).ToString() : null); return text ?? ""; } } [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] public static string SteamNumber(string id) { if (string.IsNullOrEmpty(id)) { return null; } string text = (id.StartsWith("Steam_", StringComparison.Ordinal) ? id.Substring(6) : id); if (text.Length == 0) { return null; } string text2 = text; foreach (char c in text2) { if (c < '0' || c > '9') { return null; } } return text; } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static class LimitTable { public static Dictionary<string, int> Parse(string yaml, List<string> warnings) { Dictionary<string, int> dictionary = new Dictionary<string, int>(); if (string.IsNullOrWhiteSpace(yaml)) { return dictionary; } List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); try { Parser parser = new Parser(new StringReader(yaml)); parser.Consume<YamlDotNet.Core.Events.StreamStart>(); if (!parser.TryConsume<YamlDotNet.Core.Events.DocumentStart>(out var _)) { return dictionary; } if (!parser.TryConsume<MappingStart>(out var _)) { warnings.Add("PortalLimits.yml could not be read: the root is not a mapping"); return dictionary; } MappingEnd event3; while (!parser.TryConsume<MappingEnd>(out event3)) { string value = parser.Consume<YamlDotNet.Core.Events.Scalar>().Value; string value2 = ""; if (parser.TryConsume<YamlDotNet.Core.Events.Scalar>(out var event4)) { value2 = event4.Value; } else { SkipNode(parser); } list.Add(new KeyValuePair<string, string>(value, value2)); } } catch (Exception ex) { warnings.Add("PortalLimits.yml could not be read: " + ex.Message); return new Dictionary<string, int>(); } foreach (KeyValuePair<string, string> item in list) { string text = (item.Key ?? "").Trim(); int result; if (!IsDigits(text)) { warnings.Add("Invalid Steam ID in PortalLimits.yml: " + text); } else if (!int.TryParse((item.Value ?? "").Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result) || result < 0) { warnings.Add("Invalid limit for " + text + " in PortalLimits.yml: " + item.Value); } else if (dictionary.ContainsKey(text)) { warnings.Add("Duplicate Steam ID in PortalLimits.yml, later entry ignored: " + text); } else { dictionary[text] = result; } } return dictionary; } public static int LimitFor(string ownerId, int defaultLimit, IReadOnlyDictionary<string, int> table) { string text = Identity.SteamNumber(ownerId); if (text != null && table.TryGetValue(text, out var value)) { return value; } return defaultLimit; } private static void SkipNode(Parser parser) { int num = 0; do { ParsingEvent parsingEvent = parser.Consume<ParsingEvent>(); if (parsingEvent is SequenceStart || parsingEvent is MappingStart) { num++; } else if (parsingEvent is SequenceEnd || parsingEvent is MappingEnd) { num--; } } while (num > 0); } private static bool IsDigits(string text) { if (text.Length == 0) { return false; } foreach (char c in text) { if (c < '0' || c > '9') { return false; } } return true; } } internal static class LimitRules { public static bool CanPlace(int count, int limit, bool isAdmin) { return isAdmin || limit <= 0 || count < limit; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class LimitSync { public static string Write([<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 1, 1, 0 })] IReadOnlyDictionary<string, (int Count, int Limit)> data) { StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair<string, (int, int)> datum in data) { if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } stringBuilder.Append(Uri.EscapeDataString(datum.Key)).Append('|').Append(datum.Value.Item1.ToString(CultureInfo.InvariantCulture)) .Append('|') .Append(datum.Value.Item2.ToString(CultureInfo.InvariantCulture)); } return stringBuilder.ToString(); } [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 1, 1, 0 })] public static Dictionary<string, (int Count, int Limit)> Read(string text) { Dictionary<string, (int, int)> dictionary = new Dictionary<string, (int, int)>(); if (string.IsNullOrEmpty(text)) { return dictionary; } string[] array = text.Split(new char[1] { '\n' }); foreach (string text2 in array) { string[] array2 = text2.Split(new char[1] { '|' }); if (array2.Length != 3) { return new Dictionary<string, (int, int)>(); } if (!int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { return new Dictionary<string, (int, int)>(); } string text3; try { text3 = Uri.UnescapeDataString(array2[0]); } catch (Exception) { return new Dictionary<string, (int, int)>(); } if (text3.Length == 0) { return new Dictionary<string, (int, int)>(); } dictionary[text3] = (result, result2); } return dictionary; } } internal enum PortalMode { Public, Private, Group, Guild, Admin } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class ModeRules { private static readonly PortalMode[] AllModes = new PortalMode[5] { PortalMode.Public, PortalMode.Private, PortalMode.Group, PortalMode.Guild, PortalMode.Admin }; public static bool TryParse(string text, out PortalMode mode) { switch ((text ?? "").Trim().ToLowerInvariant()) { case "public": mode = PortalMode.Public; return true; case "private": mode = PortalMode.Private; return true; case "group": mode = PortalMode.Group; return true; case "guild": mode = PortalMode.Guild; return true; case "admin": mode = PortalMode.Admin; return true; default: mode = PortalMode.Private; return false; } } public static bool IsValid(int value) { if ((uint)value <= 4u) { return true; } return false; } public static string Key(PortalMode mode) { return mode switch { PortalMode.Public => "public", PortalMode.Private => "private", PortalMode.Group => "group", PortalMode.Guild => "guild", PortalMode.Admin => "admin", _ => "private", }; } public static IReadOnlyList<PortalMode> ParseList(string text) { List<PortalMode> list = new List<PortalMode>(); if (string.IsNullOrWhiteSpace(text)) { return list; } string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { if (TryParse(text2, out var mode) && !list.Contains(mode)) { list.Add(mode); } } return list; } private static List<PortalMode> Allowed(IReadOnlyList<PortalMode> playerModes, bool isAdmin, bool groupsLoaded, bool guildAvailable) { List<PortalMode> list = new List<PortalMode>(); PortalMode[] allModes = AllModes; foreach (PortalMode portalMode in allModes) { if ((isAdmin || Contains(playerModes, portalMode)) && (portalMode != PortalMode.Group || groupsLoaded) && (portalMode != PortalMode.Guild || guildAvailable)) { list.Add(portalMode); } } return list; } private static bool Contains(IReadOnlyList<PortalMode> modes, PortalMode mode) { for (int i = 0; i < modes.Count; i++) { if (modes[i] == mode) { return true; } } return false; } public static PortalMode Next(PortalMode current, IReadOnlyList<PortalMode> playerModes, bool isAdmin, bool groupsLoaded, bool guildAvailable) { List<PortalMode> list = Allowed(playerModes, isAdmin, groupsLoaded, guildAvailable); if (list.Count == 0) { return current; } foreach (PortalMode item in list) { if (item > current) { return item; } } return list[0]; } public static PortalMode Initial(PortalMode configured, IReadOnlyList<PortalMode> playerModes, bool isAdmin, bool groupsLoaded, bool guildAvailable) { List<PortalMode> list = Allowed(playerModes, isAdmin, groupsLoaded, guildAvailable); if (list.Contains(configured)) { return configured; } return (list.Count <= 0) ? PortalMode.Private : list[0]; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class PngImage { private static readonly byte[] Signature = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 }; public static bool TryDecode(byte[] data, out int width, out int height, out Color32[] pixels) { width = 0; height = 0; pixels = Array.Empty<Color32>(); try { return Decode(data, ref width, ref height, ref pixels); } catch (Exception) { width = 0; height = 0; pixels = Array.Empty<Color32>(); return false; } } private static bool Decode(byte[] data, ref int width, ref int height, ref Color32[] pixels) { //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) if (data == null || data.Length < Signature.Length + 12) { return false; } for (int i = 0; i < Signature.Length; i++) { if (data[i] != Signature[i]) { return false; } } int num = 0; MemoryStream memoryStream = new MemoryStream(); int num2; for (int j = Signature.Length; j + 12 <= data.Length; j += 12 + num2) { num2 = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | data[j + 3]; if (num2 < 0 || j + 12 + num2 > data.Length) { return false; } string text = new string(new char[4] { (char)data[j + 4], (char)data[j + 5], (char)data[j + 6], (char)data[j + 7] }); int num3 = j + 8; switch (text) { case "IHDR": { if (num2 < 13) { return false; } width = (data[num3] << 24) | (data[num3 + 1] << 16) | (data[num3 + 2] << 8) | data[num3 + 3]; height = (data[num3 + 4] << 24) | (data[num3 + 5] << 16) | (data[num3 + 6] << 8) | data[num3 + 7]; byte b = data[num3 + 8]; byte b2 = data[num3 + 9]; byte b3 = data[num3 + 12]; if (b != 8 || b3 != 0) { return false; } switch (b2) { case 6: num = 4; break; case 2: num = 3; break; default: return false; } continue; } case "IDAT": memoryStream.Write(data, num3, num2); continue; default: continue; case "IEND": break; } break; } if (num == 0 || width <= 0 || height <= 0 || memoryStream.Length < 2) { return false; } int num4 = width * num; byte[] array = new byte[(num4 + 1) * height]; memoryStream.Position = 2L; using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress)) { int num5; for (int k = 0; k < array.Length; k += num5) { num5 = deflateStream.Read(array, k, array.Length - k); if (num5 <= 0) { return false; } } } byte[] array2 = new byte[num4]; byte[] array3 = new byte[num4]; Color32[] array4 = (Color32[])(object)new Color32[width * height]; for (int l = 0; l < height; l++) { int num6 = l * (num4 + 1); byte b4 = array[num6]; for (int m = 0; m < num4; m++) { int num7 = array[num6 + 1 + m]; int num8 = ((m >= num) ? array3[m - num] : 0); int num9 = array2[m]; int upLeft = ((m >= num) ? array2[m - num] : 0); switch (b4) { case 1: num7 += num8; break; case 2: num7 += num9; break; case 3: num7 += num8 + num9 >> 1; break; case 4: num7 += Paeth(num8, num9, upLeft); break; default: return false; case 0: break; } array3[m] = (byte)num7; } int num10 = (height - 1 - l) * width; for (int n = 0; n < width; n++) { int num11 = n * num; byte b5 = ((num == 4) ? array3[num11 + 3] : byte.MaxValue); array4[num10 + n] = new Color32(array3[num11], array3[num11 + 1], array3[num11 + 2], b5); } byte[] array5 = array2; array2 = array3; array3 = array5; } pixels = array4; return true; } private static int Paeth(int left, int up, int upLeft) { int num = left + up - upLeft; int num2 = Math.Abs(num - left); int num3 = Math.Abs(num - up); int num4 = Math.Abs(num - upLeft); if (num2 <= num3 && num2 <= num4) { return left; } if (num3 <= num4) { return up; } return upLeft; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal sealed class RevisionTracker<TKey> { [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 1, 1, 0 })] private readonly Dictionary<TKey, (uint Data, ushort Owner)> _seen = new Dictionary<TKey, (uint, ushort)>(); public int Count => _seen.Count; public bool Changed(TKey key, uint dataRevision, ushort ownerRevision) { (uint, ushort) tuple = (dataRevision, ownerRevision); if (_seen.TryGetValue(key, out (uint, ushort) value)) { var (num, num2) = value; var (num3, num4) = tuple; if (num == num3 && num2 == num4) { return false; } } _seen[key] = tuple; return true; } public void Prune(ICollection<TKey> present) { if (_seen.Count == 0) { return; } List<TKey> list = new List<TKey>(); foreach (TKey key in _seen.Keys) { if (!present.Contains(key)) { list.Add(key); } } foreach (TKey item in list) { _seen.Remove(item); } } public void Remove(TKey key) { _seen.Remove(key); } public void Clear() { _seen.Clear(); } } internal static class LimitClient { private static int _pending; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] private static string _lastText = ""; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 1, 1, 0 })] private static Dictionary<string, (int Count, int Limit)> _data = new Dictionary<string, (int, int)>(); public static void Reset() { _pending = 0; _lastText = ""; _data = new Dictionary<string, (int, int)>(); } public static void AddPending() { _pending++; } public static (int Count, int Limit) Mine() { string text = LimitServer.Published.Value ?? ""; if (!string.Equals(text, _lastText, StringComparison.Ordinal)) { _lastText = text; int num; if (_data.TryGetValue(Identity.Local, out (int, int) value)) { (num, _) = value; } else { num = -1; } int num2 = num; _data = LimitSync.Read(text); int num3; if (_data.TryGetValue(Identity.Local, out (int, int) value2)) { (num3, _) = value2; } else { num3 = -1; } int num4 = num3; if (num2 != num4) { _pending = 0; } } int value3 = VikingsPortalsPlugin.LimitPerAccount.Value; if (!_data.TryGetValue(Identity.Local, out (int, int) value4)) { return (Count: _pending, Limit: value3); } return (Count: value4.Item1 + _pending, Limit: value4.Item2); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [HarmonyPatch(typeof(Player), "TryPlacePiece", new Type[] { typeof(Piece) })] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class Player_TryPlacePiece_Limits { private static bool Prefix(Piece piece, ref bool __result) { if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent<TeleportWorld>() == (Object)null) { return true; } if (VikingsPortalsPlugin.IsLocalAdmin()) { return true; } if (!LimitRules.CanPlace(PortalRegistry.Count, VikingsPortalsPlugin.LimitWorld.Value, isAdmin: false)) { PortalProtection.Notify("$vportals_world_limit"); __result = false; return false; } (int, int) tuple = LimitClient.Mine(); if (!LimitRules.CanPlace(tuple.Item1, tuple.Item2, isAdmin: false)) { string token = Localization.instance.Localize("$vportals_account_limit", new string[1] { tuple.Item2.ToString(CultureInfo.InvariantCulture) }); PortalProtection.Notify(token); __result = false; return false; } return true; } private static void Postfix(Piece piece, bool __result) { if (__result && (Object)(object)piece != (Object)null && (Object)(object)((Component)piece).GetComponent<TeleportWorld>() != (Object)null) { LimitClient.AddPending(); } } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class ZNet_Awake_ResetLimitClient { private static void Postfix() { LimitClient.Reset(); } } [HarmonyPatch(typeof(ZNet), "Shutdown")] internal static class ZNet_Shutdown_ResetLimitClient { private static void Postfix() { LimitClient.Reset(); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class LimitServer { public const string SyncKey = "VPortals_Limits"; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1 })] private static CustomSyncedValue<string> _published; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static FileSystemWatcher _watcher; private static Dictionary<string, int> _table = new Dictionary<string, int>(); private static string _path = ""; private static long _lastWrite; private static bool _reloadScheduled; private static bool _started; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static string _lastPublished; public static CustomSyncedValue<string> Published { get { if (_published == null) { _published = new CustomSyncedValue<string>(VikingsPortalsPlugin.Sync, "VPortals_Limits", ""); } return _published; } } public static void Start() { Stop(); _started = true; _lastPublished = null; string text = Path.Combine(Paths.ConfigPath, "VikingsPortals"); _path = Path.Combine(text, "PortalLimits.yml"); try { Directory.CreateDirectory(text); if (!File.Exists(_path)) { File.WriteAllText(_path, ""); } } catch (Exception ex) { VikingsPortalsPlugin.Log.LogWarning((object)("PortalLimits.yml could not be created: " + ex.Message)); } Load(); StartWatcher(text); PortalRegistry.Changed += Publish; VikingsPortalsPlugin.LimitPerAccount.SettingChanged += OnSettingChanged; Publish(); ((MonoBehaviour)ZNet.instance).StartCoroutine(RecountLoop()); } private static IEnumerator RecountLoop() { while (_started) { yield return (object)new WaitForSeconds(5f); if (_started) { Publish(); } } } public static void Stop() { if (!_started) { return; } _started = false; PortalRegistry.Changed -= Publish; VikingsPortalsPlugin.LimitPerAccount.SettingChanged -= OnSettingChanged; if (_watcher != null) { try { _watcher.EnableRaisingEvents = false; _watcher.Dispose(); } catch (Exception) { } _watcher = null; } _reloadScheduled = false; } private static void OnSettingChanged(object sender, EventArgs args) { Publish(); } private static void StartWatcher(string folder) { try { _watcher = new FileSystemWatcher(folder, "PortalLimits.yml") { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), SynchronizingObject = ThreadingHelper.SynchronizingObject }; _watcher.Changed += OnFileChanged; _watcher.Created += OnFileChanged; _watcher.Renamed += [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (object sender, RenamedEventArgs args) => { OnFileChanged(sender, args); }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { _watcher?.Dispose(); _watcher = null; VikingsPortalsPlugin.Log.LogWarning((object)("Automatic PortalLimits.yml reload is unavailable: " + ex.Message)); } } private static void OnFileChanged(object sender, FileSystemEventArgs args) { _lastWrite = Stopwatch.GetTimestamp(); if (!_reloadScheduled && !((Object)(object)ZNet.instance == (Object)null)) { _reloadScheduled = true; ((MonoBehaviour)ZNet.instance).StartCoroutine(ReloadAfterQuietPeriod()); } } private static IEnumerator ReloadAfterQuietPeriod() { try { while (_started && (double)(Stopwatch.GetTimestamp() - _lastWrite) / (double)Stopwatch.Frequency < 0.75) { yield return null; } if (_started) { Load(); Publish(); } } finally { _reloadScheduled = false; } } private static void Load() { List<string> list = new List<string>(); string yaml = ""; try { if (File.Exists(_path)) { yaml = File.ReadAllText(_path); } } catch (Exception ex) { VikingsPortalsPlugin.Log.LogWarning((object)("PortalLimits.yml could not be read: " + ex.Message)); return; } _table = LimitTable.Parse(yaml, list); foreach (string item in list) { VikingsPortalsPlugin.Log.LogWarning((object)item); } } private static void Publish() { int value = VikingsPortalsPlugin.LimitPerAccount.Value; Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (ZDO item in PortalRegistry.All) { string text = item.GetString("VPortals_OwnerId", ""); if (text.Length != 0) { dictionary.TryGetValue(text, out var value2); dictionary[text] = value2 + 1; } } Dictionary<string, (int, int)> dictionary2 = new Dictionary<string, (int, int)>(); foreach (KeyValuePair<string, int> item2 in dictionary) { dictionary2[item2.Key] = (item2.Value, LimitTable.LimitFor(item2.Key, value, _table)); } foreach (KeyValuePair<string, int> item3 in _table) { string key = "Steam_" + item3.Key; if (!dictionary2.ContainsKey(key)) { dictionary2[key] = (0, item3.Value); } } string text2 = LimitSync.Write(dictionary2); if (!string.Equals(text2, _lastPublished, StringComparison.Ordinal)) { _lastPublished = text2; Published.Value = text2; } } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class ZNet_Awake_StartLimits { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(ZNet __instance) { if (__instance.IsServer()) { LimitServer.Start(); } } } [HarmonyPatch(typeof(ZNet), "Shutdown")] internal static class ZNet_Shutdown_StopLimits { private static void Prefix() { LimitServer.Stop(); } } internal class PortalExitWatcher : MonoBehaviour { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private void OnTriggerExit(Collider other) { if (!PortalSelection.Active || (Object)(object)other == (Object)null) { return; } Player component = ((Component)other).GetComponent<Player>(); if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer) { return; } ZDO source = PortalSelection.Source; if (source != null) { ZNetView componentInParent = ((Component)this).GetComponentInParent<ZNetView>(); ZDO val = (((Object)(object)componentInParent != (Object)null && componentInParent.IsValid()) ? componentInParent.GetZDO() : null); if (val != source) { return; } } if ((Object)(object)Minimap.instance != (Object)null) { Minimap.instance.SetMapMode((MapMode)1); } PortalSelection.End(); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake_PortalExitWatcher { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [HarmonyPriority(0)] private static void Postfix(ZNetScene __instance) { foreach (GameObject prefab in __instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab.GetComponent<TeleportWorld>() == (Object)null)) { Transform val = prefab.transform.Find("TELEPORT"); if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponent<PortalExitWatcher>() != (Object)null)) { ((Component)val).gameObject.AddComponent<PortalExitWatcher>(); } } } } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static class PortalFavorites { public const string DataKey = "VPortals_Favorites"; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] [method: <596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] [field: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] public static event Action Changed; public static HashSet<string> Current() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || localPlayer.m_customData == null) { return new HashSet<string>(StringComparer.Ordinal); } localPlayer.m_customData.TryGetValue("VPortals_Favorites", out var value); return FavoriteList.Read(value ?? ""); } public static bool IsFavorite(HashSet<string> favorites, ZDO portal) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return portal != null && favorites.Contains(FavoriteList.Key(portal.GetPosition())); } public static void Toggle(ZDO portal) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && localPlayer.m_customData != null && portal != null && portal.IsValid()) { HashSet<string> hashSet = Current(); string item = FavoriteList.Key(portal.GetPosition()); if (!hashSet.Remove(item)) { hashSet.Add(item); } string text = FavoriteList.Write(hashSet); if (text.Length == 0) { localPlayer.m_customData.Remove("VPortals_Favorites"); } else { localPlayer.m_customData["VPortals_Favorites"] = text; } PortalFavorites.Changed?.Invoke(); } } } [HarmonyPatch(typeof(Minimap), "Update")] internal static class Minimap_Update_FavoritesPanel { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(Minimap __instance) { FavoritesPanel.Refresh(__instance); } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static class FavoritesPanel { private static readonly Color PanelColor = new Color(0f, 0f, 0f, 0.75f); private static readonly Color RowColor = new Color(1f, 1f, 1f, 0.05f); private static readonly Color RowHoverColor = new Color(1f, 1f, 1f, 0.15f); private static readonly Color FavoriteColor = new Color(1f, 0.82f, 0.3f, 1f); private static readonly List<FavoritesPanelRow> Rows = new List<FavoritesPanelRow>(); [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static GameObject _root; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static RectTransform _content; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private static TMP_FontAsset _font; private static bool _subscribed; private static bool _dirty = true; private static bool _visible; private static int _count; public static bool PointerOver() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if ((Object)(object)_root == (Object)null || !_root.activeInHierarchy) { return false; } return RectTransformUtility.RectangleContainsScreenPoint((RectTransform)_root.transform, Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null); } public static void Refresh(Minimap minimap) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (!((Object)(object)Player.m_localPlayer != (Object)null) || (int)minimap.m_mode != 2 || PortalPins.Shown.Count <= 0) { _visible = false; if ((Object)(object)_root != (Object)null && _root.activeSelf) { _root.SetActive(false); } } else if (Ensure(minimap) && !((Object)(object)_root == (Object)null)) { if (!_visible) { _visible = true; _dirty = true; } if (_dirty) { Rebuild(); } bool flag = _count > 0; if (_root.activeSelf != flag) { _root.SetActive(flag); } } } internal static void MarkDirty() { _dirty = true; } private static void Rebuild() { _dirty = false; if ((Object)(object)_content == (Object)null) { return; } HashSet<string> favorites = PortalFavorites.Current(); IReadOnlyList<KeyValuePair<PinData, ZDO>> readOnlyList = FavoriteList.Favorites(PortalPins.Shown, [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] (KeyValuePair<PinData, ZDO> pair) => pair.Key.m_name, [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(0)] (KeyValuePair<PinData, ZDO> pair) => PortalFavorites.IsFavorite(favorites, pair.Value)); for (int num = 0; num < readOnlyList.Count; num++) { if (num >= Rows.Count) { Rows.Add(CreateRow((Transform)(object)_content)); } KeyValuePair<PinData, ZDO> keyValuePair = readOnlyList[num]; Rows[num].Show(keyValuePair.Key, keyValuePair.Value); } for (int num2 = readOnlyList.Count; num2 < Rows.Count; num2++) { Rows[num2].Hide(); } _count = readOnlyList.Count; } private static bool Ensure(Minimap minimap) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown if ((Object)(object)_root != (Object)null) { return true; } if ((Object)(object)minimap.m_largeRoot == (Object)null || Localization.instance == null) { return false; } Rows.Clear(); if (!_subscribed) { _subscribed = true; PortalPins.PinsChanged += MarkDirty; PortalFavorites.Changed += MarkDirty; } _font = (((Object)(object)minimap.m_biomeNameLarge != (Object)null) ? minimap.m_biomeNameLarge.font : null); _root = new GameObject("VPortals_FavoritesPanel", new Type[1] { typeof(RectTransform) }); _root.SetActive(false); _root.transform.SetParent(minimap.m_largeRoot.transform, false); _root.transform.SetAsLastSibling(); RectTransform val = (RectTransform)_root.transform; val.anchorMin = new Vector2(0f, 0.5f); val.anchorMax = new Vector2(0f, 0.5f); val.pivot = new Vector2(0f, 0.5f); val.anchoredPosition = new Vector2(30f, 0f); val.sizeDelta = new Vector2(320f, 560f); Image val2 = _root.AddComponent<Image>(); ((Graphic)val2).color = PanelColor; ((Graphic)val2).raycastTarget = true; VerticalLayoutGroup val3 = _root.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val3).padding = new RectOffset(10, 10, 10, 10); ((HorizontalOrVerticalLayoutGroup)val3).spacing = 8f; ((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false; TextMeshProUGUI val4 = CreateText(_root.transform, "Title", 22f); ((TMP_Text)val4).text = Localization.instance.Localize("$vportals_favorites"); ((TMP_Text)val4).fontStyle = (FontStyles)1; ((TMP_Text)val4).alignment = (TextAlignmentOptions)514; Fixed(((Component)val4).gameObject, 30f); _content = CreateList(_root.transform); _dirty = true; return true; } private static RectTransform CreateList(Transform parent) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_005c: 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_008c: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown GameObject val = new GameObject("List", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); LayoutElement val2 = val.AddComponent<LayoutElement>(); val2.flexibleHeight = 1f; Image val3 = val.AddComponent<Image>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.01f); val.AddComponent<RectMask2D>(); GameObject val4 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val.transform, false); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = new Vector2(0f, 1f); val5.anchorMax = new Vector2(1f, 1f); val5.pivot = new Vector2(0.5f, 1f); val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; VerticalLayoutGroup val6 = val4.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val6).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)val6).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val6).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandHeight = false; ContentSizeFitter val7 = val4.AddComponent<ContentSizeFitter>(); val7.verticalFit = (FitMode)2; ScrollRect val8 = val.AddComponent<ScrollRect>(); val8.viewport = (RectTransform)val.transform; val8.content = val5; val8.horizontal = false; val8.vertical = true; val8.movementType = (MovementType)2; val8.scrollSensitivity = 30f; return val5; } private static FavoritesPanelRow CreateRow(Transform parent) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = RowColor; HorizontalLayoutGroup val3 = val.AddComponent<HorizontalLayoutGroup>(); ((LayoutGroup)val3).padding = new RectOffset(6, 6, 3, 3); ((HorizontalOrVerticalLayoutGroup)val3).spacing = 8f; ((LayoutGroup)val3).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = false; Fixed(val, 30f); GameObject val4 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val.transform, false); Image val5 = val4.AddComponent<Image>(); val5.sprite = PortalPins.Icon; val5.preserveAspect = true; ((Graphic)val5).raycastTarget = false; LayoutElement val6 = val4.AddComponent<LayoutElement>(); val6.preferredWidth = 24f; val6.preferredHeight = 24f; val6.minWidth = 24f; val6.minHeight = 24f; TextMeshProUGUI val7 = CreateText(val.transform, "Name", 18f); ((TMP_Text)val7).alignment = (TextAlignmentOptions)4097; ((TMP_Text)val7).overflowMode = (TextOverflowModes)1; ((TMP_Text)val7).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val7).richText = false; ((Component)val7).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f; FavoritesPanelRow favoritesPanelRow = val.AddComponent<FavoritesPanelRow>(); favoritesPanelRow.Setup(val2, val7, RowColor, RowHoverColor, FavoriteColor); return favoritesPanelRow; } private static TextMeshProUGUI CreateText(Transform parent, string name, float size) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); if ((Object)(object)_font != (Object)null) { ((TMP_Text)val2).font = _font; } ((TMP_Text)val2).fontSize = size; ((Graphic)val2).color = Color.white; ((Graphic)val2).raycastTarget = false; return val2; } private static void Fixed(GameObject go, float height) { LayoutElement val = go.GetComponent<LayoutElement>(); if ((Object)(object)val == (Object)null) { val = go.AddComponent<LayoutElement>(); } val.minHeight = height; val.preferredHeight = height; } } internal class FavoritesPanelRow : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler { [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private Image _background; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private TextMeshProUGUI _label; private Color _normal; private Color _hover; private Color _favorite; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private PinData _pin; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] private ZDO _portal; [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public void Setup(Image background, TextMeshProUGUI label, Color normal, Color hover, Color favorite) { //IL_0010: 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_0017: 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_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) _background = background; _label = label; _normal = normal; _hover = hover; _favorite = favorite; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public void Show(PinData pin, ZDO portal) { //IL_0070: 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) _pin = pin; _portal = portal; if ((Object)(object)_label != (Object)null) { ((TMP_Text)_label).text = (string.IsNullOrEmpty(pin.m_name) ? "?" : pin.m_name); ((Graphic)_label).color = _favorite; } if ((Object)(object)_background != (Object)null) { ((Graphic)_background).color = _normal; } if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } } public void Hide() { _pin = null; _portal = null; if (((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(false); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public void OnPointerClick(PointerEventData eventData) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if (_pin == null || _portal == null) { return; } if ((int)eventData.button == 0) { if (PortalSelection.Active) { PortalSelection.TryTeleport(_portal, _pin); } } else if ((int)eventData.button == 1) { PortalFavorites.Toggle(_portal); } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public void OnPointerEnter(PointerEventData eventData) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_background != (Object)null) { ((Graphic)_background).color = _hover; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public void OnPointerExit(PointerEventData eventData) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_background != (Object)null) { ((Graphic)_background).color = _normal; } } } [HarmonyPatch(typeof(Minimap), "UpdateMap")] internal static class Minimap_UpdateMap_PanelWheel { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Prefix(Minimap __instance, ref bool takeInput) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 if (takeInput && (int)__instance.m_mode == 2 && FavoritesPanel.PointerOver()) { takeInput = false; } } } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] internal static class PortalPins { [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] public const string IconResource = "VikingsPortals.assets.portal_icon.png"; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] private static readonly Dictionary<PinData, ZDO> ShownPins = new Dictionary<PinData, ZDO>(); [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] private static readonly Dictionary<ZDO, PinData> PinsByPortal = new Dictionary<ZDO, PinData>(); private static Sprite _icon; private static bool _dirty; public static int PinType { get; private set; } = -1; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(1)] public static IReadOnlyDictionary<PinData, ZDO> Shown { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] get { return ShownPins; } } public static bool Visible { get; private set; } internal static bool[] IconTypes { get; private set; } [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1 })] [field: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1 })] internal static List<PinData> AllPins { [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1 })] get; [param: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(new byte[] { 2, 1 })] private set; } internal static Sprite Icon { get { if ((Object)(object)_icon == (Object)null) { _icon = LoadIcon(); } return _icon; } } public static event Action PinsChanged; public static void Refresh() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || PinType < 0) { return; } Dictionary<ZDO, string> dictionary = new Dictionary<ZDO, string>(); foreach (ZDO item in PortalRegistry.All) { if (item != null && item.IsValid() && PortalRecord.LocalCanUse(item)) { dictionary[item] = item.GetString(ZDOVars.s_tag, ""); } } bool flag = false; List<ZDO> list = new List<ZDO>(); foreach (KeyValuePair<ZDO, PinData> item2 in PinsByPortal) { if (!dictionary.TryGetValue(item2.Key, out var value) || item2.Value.m_name != value || item2.Value.m_pos != item2.Key.GetPosition()) { list.Add(item2.Key); } } foreach (ZDO item3 in list) { PinData val = PinsByPortal[item3]; instance.RemovePin(val); ShownPins.Remove(val); PinsByPortal.Remove(item3); flag = true; } foreach (KeyValuePair<ZDO, string> item4 in dictionary) { if (!PinsByPortal.ContainsKey(item4.Key)) { PinData val2 = instance.AddPin(item4.Key.GetPosition(), (PinType)PinType, item4.Value, false, false, 0L, default(PlatformUserID)); ShownPins[val2] = item4.Key; PinsByPortal[item4.Key] = val2; flag = true; } } if (flag) { PortalPins.PinsChanged?.Invoke(); } } public static void Clear() { Minimap instance = Minimap.instance; bool flag = ShownPins.Count > 0; if ((Object)(object)instance != (Object)null) { foreach (PinData key in ShownPins.Keys) { instance.RemovePin(key); } } ShownPins.Clear(); PinsByPortal.Clear(); if (flag) { PortalPins.PinsChanged?.Invoke(); } } public static void ToggleVisible() { Visible = !Visible; if (!PortalSelection.Active) { if (Visible) { Refresh(); } else { Clear(); } } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static void Register(Minimap minimap, ref bool[] visibleIconTypes, List<PinData> pins) { //IL_0044: 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_005e: Unknown result type (might be due to invalid IL or missing references) ShownPins.Clear(); PinsByPortal.Clear(); PortalSelection.Reset(); int num = visibleIconTypes.Length; bool[] array = new bool[num + 1]; Array.Copy(visibleIconTypes, array, num); array[num] = true; visibleIconTypes = array; minimap.m_icons.Add(new SpriteData { m_name = (PinType)num, m_icon = Icon }); PinType = num; IconTypes = array; AllPins = pins; ((MonoBehaviour)minimap).StartCoroutine(RefreshLoop()); } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] internal static void Track(bool[] visibleIconTypes, List<PinData> pins) { IconTypes = visibleIconTypes; AllPins = pins; } internal static void MarkDirty() { _dirty = true; } internal static bool ConsumeDirty() { if (!_dirty) { return false; } _dirty = false; return true; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [return: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] internal static PinData PinNear(Minimap minimap, Vector3 screenPoint) { //IL_001d: 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_00a1: Unknown result type (might be due to invalid IL or missing references) if (ShownPins.Count == 0) { return null; } if (!ScreenToWorld(minimap, screenPoint, out var world)) { return null; } float num = minimap.m_removeRadius * minimap.LargeZoom * 2f; PinData result = null; float num2 = float.MaxValue; foreach (PinData key in ShownPins.Keys) { if (!((Object)(object)key.m_uiElement == (Object)null) && ((Component)key.m_uiElement).gameObject.activeInHierarchy) { float num3 = Utils.DistanceXZ(world, key.m_pos); if (num3 < num && num3 < num2) { result = key; num2 = num3; } } } return result; } internal static bool KeyDown() { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = VikingsPortalsPlugin.MapPinsKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0) { return false; } if (!ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, false)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } internal static bool TakesInput() { if (GameCamera.InFreeFly()) { return false; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return false; } if (Menu.IsVisible() || Console.IsVisible() || TextInput.IsVisible() || Minimap.InTextInput()) { return false; } if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_buildUi != (Object)null && Hud.instance.m_buildUi.SearchFieldFocused) { return false; } if (ZInput.IsGamepadActive() && (Minimap.IsOpen() || InventoryGui.IsVisible() || StoreGui.IsVisible() || Hud.IsPieceSelectionVisible())) { return false; } return !PlayerCustomizaton.IsBarberGuiVisible(); } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool ScreenToWorld(Minimap minimap, Vector3 screenPoint, out Vector3 world) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) world = Vector3.zero; RawImage mapImageLarge = minimap.m_mapImageLarge; if ((Object)(object)mapImageLarge == (Object)null) { return false; } RectTransform rectTransform = ((Graphic)mapImageLarge).rectTransform; Vector2 val = default(Vector2); if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Vector2.op_Implicit(screenPoint), (Camera)null, ref val)) { return false; } Rect rect = rectTransform.rect; if (!((Rect)(ref rect)).Contains(val)) { return false; } Vector2 val2 = Rect.PointToNormalized(rectTransform.rect, val); Rect uvRect = mapImageLarge.uvRect; int num = minimap.m_textureSize / 2; float num2 = (((Rect)(ref uvRect)).xMin + val2.x * ((Rect)(ref uvRect)).width) * (float)minimap.m_textureSize - (float)num; float num3 = (((Rect)(ref uvRect)).yMin + val2.y * ((Rect)(ref uvRect)).height) * (float)minimap.m_textureSize - (float)num; world = new Vector3(num2 * minimap.m_pixelSize, 0f, num3 * minimap.m_pixelSize); return true; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static IEnumerator RefreshLoop() { yield return null; while (true) { if (Visible && !PortalSelection.Active) { Refresh(); } yield return (object)new WaitForSeconds(1f); } } private static Sprite LoadIcon() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) using Stream stream = typeof(PortalPins).Assembly.GetManifestResourceStream("VikingsPortals.assets.portal_icon.png"); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); if (!PngImage.TryDecode(memoryStream.ToArray(), out var width, out var height, out var pixels)) { return null; } Texture2D val = new Texture2D(width, height, (TextureFormat)4, false); val.SetPixels32(pixels); val.Apply(); ((Object)val).name = "VPortals_Icon"; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)val2).name = "VPortals_Icon"; return val2; } } [HarmonyPatch(typeof(Minimap), "Start")] internal static class Minimap_Start_PortalPins { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(Minimap __instance, ref bool[] ___m_visibleIconTypes, List<PinData> ___m_pins) { PortalPins.Register(__instance, ref ___m_visibleIconTypes, ___m_pins); } } [HarmonyPatch(typeof(Minimap), "Update")] internal static class Minimap_Update_PortalKeys { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Prefix(Minimap __instance, bool[] ___m_visibleIconTypes, List<PinData> ___m_pins, ref bool ___m_pinUpdateRequired) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 PortalPins.Track(___m_visibleIconTypes, ___m_pins); if (PortalPins.ConsumeDirty()) { ___m_pinUpdateRequired = true; } if (!((Object)(object)Player.m_localPlayer == (Object)null) && (VikingsPortalsPlugin.MapPinsOnMinimap.Value ? ((int)__instance.m_mode > 0) : ((int)__instance.m_mode == 2)) && PortalPins.KeyDown() && PortalPins.TakesInput()) { PortalPins.ToggleVisible(); } } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class PortalSelection { private static bool[] _savedIconTypes; private static bool _sourceAllowsAllItems; public static bool Active { get; private set; } public static ZDO Source { get; private set; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public static void Begin(TeleportWorld source) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Invalid comparison between Unknown and I4 Minimap instance = Minimap.instance; if ((Object)(object)source == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if (Active) { End(); } bool noMap = Game.m_noMap; Game.m_noMap = false; try { instance.ShowPointOnMap(((Component)source).transform.position); } finally { Game.m_noMap = noMap; } if ((int)instance.m_mode == 2) { ZNetView component = ((Component)source).GetComponent<ZNetView>(); Source = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); _sourceAllowsAllItems = source.m_allowAllItems; Active = true; if (InventoryGui.IsVisible()) { InventoryGui.instance.Hide(); } PortalPins.Refresh(); if (VikingsPortalsPlugin.MapHidePins.Value) { HideOtherIcons(instance); } } } public static void End() { if (Active) { Active = false; Source = null; RestoreIcons(); if (!PortalPins.Visible) { PortalPins.Clear(); } } } internal static void Reset() { Active = false; Source = null; _savedIconTypes = null; } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void HideOtherIcons(Minimap minimap) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected I4, but got Unknown bool[] iconTypes = PortalPins.IconTypes; if (iconTypes == null || _savedIconTypes != null) { return; } _savedIconTypes = (bool[])iconTypes.Clone(); HashSet<int> hashSet = new HashSet<int> { PortalPins.PinType }; if (VikingsPortalsPlugin.MapShowPlayers.Value) { hashSet.Add(10); } HashSet<Sprite> hashSet2 = new HashSet<Sprite>(); foreach (LocationSpriteData locationIcon in minimap.m_locationIcons) { if ((Object)(object)locationIcon.m_icon != (Object)null) { hashSet2.Add(locationIcon.m_icon); } } List<PinData> allPins = PortalPins.AllPins; if (allPins != null) { foreach (PinData item in allPins) { if ((Object)(object)item.m_icon != (Object)null && hashSet2.Contains(item.m_icon)) { hashSet.Add((int)item.m_type); } } } for (int i = 0; i < iconTypes.Length; i++) { if (!hashSet.Contains(i)) { iconTypes[i] = false; } } PortalPins.MarkDirty(); } private static void RestoreIcons() { bool[] savedIconTypes = _savedIconTypes; _savedIconTypes = null; bool[] iconTypes = PortalPins.IconTypes; if (savedIconTypes == null || iconTypes == null) { return; } int num = Mathf.Min(savedIconTypes.Length, iconTypes.Length); for (int i = 0; i < num; i++) { if (savedIconTypes[i] && !iconTypes[i]) { iconTypes[i] = true; } } PortalPins.MarkDirty(); } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] public static bool TryTeleport(ZDO target, PinData pin) { //IL_00d5: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Active || (Object)(object)localPlayer == (Object)null || target == null || pin == null || !target.IsValid()) { return false; } if (!PortalRecord.LocalCanUse(target)) { ((Character)localPlayer).Message((MessageType)2, "$vportals_no_access", 0, (Sprite)null, false); return false; } string text = WorldBlock(); if (text != null) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); return false; } ItemRule value = VikingsPortalsPlugin.TeleportItemRule.Value; if ((value == ItemRule.Strict || (value == ItemRule.Portal && !_sourceAllowsAllItems)) && !((Humanoid)localPlayer).IsTeleportable(false)) { ((Character)localPlayer).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null, false); return false; } Quaternion rotation = target.GetRotation(); End(); if ((Object)(object)Minimap.instance != (Object)null) { Minimap.instance.SetMapMode((MapMode)1); } if (!((Character)localPlayer).TeleportTo(pin.m_pos + rotation * Vector3.forward + Vector3.up, rotation, true)) { return false; } if ((Object)(object)Game.instance != (Object)null) { Game.instance.IncrementPlayerStat((PlayerStatType)15, 1f, false); } return true; } public static string WorldBlock() { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return null; } if (instance.GetGlobalKey((GlobalKeys)32)) { return "$msg_blocked"; } if (!instance.GetGlobalKey((GlobalKeys)33)) { return null; } bool flag = (Object)(object)RandEventSystem.instance != (Object)null && RandEventSystem.instance.GetBossEvent() != null; float num = default(float); bool flag2 = instance.GetGlobalKey((GlobalKeys)47, ref num) && num > 0f; return (flag || flag2) ? "$msg_blockedbyboss" : null; } } [HarmonyPatch(typeof(TeleportWorldTrigger), "OnTriggerEnter")] internal static class TeleportWorldTrigger_OnTriggerEnter_Select { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool Prefix(Collider colliderIn, TeleportWorld ___m_teleportWorld) { if ((Object)(object)colliderIn == (Object)null) { return true; } Player component = ((Component)colliderIn).GetComponent<Player>(); if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer) { return true; } if ((Object)(object)___m_teleportWorld == (Object)null || !PortalRecord.IsManaged(___m_teleportWorld)) { return true; } ZDO val = PortalRecord.ZdoOf((Component)(object)___m_teleportWorld); if (val == null) { return true; } if (!PortalRecord.LocalCanUse(val)) { ((Character)component).Message((MessageType)2, "$vportals_no_access", 0, (Sprite)null, false); return false; } string text = PortalSelection.WorldBlock(); if (text != null) { ((Character)component).Message((MessageType)2, text, 0, (Sprite)null, false); return false; } PortalSelection.Begin(___m_teleportWorld); return false; } } [HarmonyPatch(typeof(Minimap), "SetMapMode")] internal static class Minimap_SetMapMode_EndSelection { private static void Postfix(MapMode mode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)mode != 2) { PortalSelection.End(); } } } [HarmonyPatch(typeof(Minimap), "OnMapDblClick")] internal static class Minimap_OnMapDblClick_BlockSelection { private static bool Prefix() { return !PortalSelection.Active; } } [HarmonyPatch(typeof(Minimap), "OnMapMiddleClick")] internal static class Minimap_OnMapMiddleClick_BlockSelection { private static bool Prefix() { return !PortalSelection.Active; } } [HarmonyPatch(typeof(Minimap), "RemovePinUnderPointer")] internal static class Minimap_RemovePinUnderPointer_BlockSelection { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool Prefix(Minimap __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!PortalSelection.Active) { return true; } PinData val = PortalPins.PinNear(__instance, ZInput.pointerPosition); if (val != null && PortalPins.Shown.TryGetValue(val, out var value)) { PortalFavorites.Toggle(value); } return false; } } [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] internal static class Minimap_OnMapLeftClick_Teleport { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool Prefix(Minimap __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!PortalSelection.Active) { return true; } PinData val = PortalPins.PinNear(__instance, ZInput.pointerPosition); if (val != null && PortalPins.Shown.TryGetValue(val, out var value)) { PortalSelection.TryTeleport(value, val); } return false; } } [HarmonyPatch(typeof(TeleportWorld), "HaveTarget")] internal static class TeleportWorld_HaveTarget_Managed { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool Prefix(TeleportWorld __instance, ref bool __result) { if (!PortalRecord.IsManaged(__instance)) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(TeleportWorld), "TargetFound")] internal static class TeleportWorld_TargetFound_Managed { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static bool Prefix(TeleportWorld __instance, ref bool __result) { if (!PortalRecord.IsManaged(__instance)) { return true; } __result = VikingsPortalsPlugin.GlowEnabled.Value; return false; } } [HarmonyPatch(typeof(Game), "ConnectPortals")] internal static class Game_ConnectPortals_Skip { private static bool Prefix() { return VikingsPortalsPlugin.PortalVanillaOnly.Value; } } [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(0)] internal static class PortalRegistry { private static HashSet<ZDO> _portals = new HashSet<ZDO>(); private static readonly RevisionTracker<ZDOID> Sent = new RevisionTracker<ZDOID>(); public static IReadOnlyCollection<ZDO> All => _portals; public static int Count => _portals.Count; [<7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] [method: <596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(2)] [field: <7a806118-b484-4911-b895-cee4047d3ab8>Nullable(2)] public static event Action Changed; public static void Clear() { Sent.Clear(); if (_portals.Count != 0) { _portals = new HashSet<ZDO>(); PortalRegistry.Changed?.Invoke(); } } public static void Add(ZDO zdo) { if (zdo != null && _portals.Add(zdo)) { PortalRegistry.Changed?.Invoke(); } } public static void Remove(ZDO zdo) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (zdo != null) { Sent.Remove(zdo.m_uid); if (_portals.Remove(zdo)) { PortalRegistry.Changed?.Invoke(); } } } public static IEnumerator Scan() { while (true) { if (ZDOMan.instance != null && (Object)(object)ZNet.instance != (Object)null) { HashSet<ZDO> found = new HashSet<ZDO>(); foreach (KeyValuePair<SectorIndex, List<ZDO>> portal in ZDOMan.instance.GetPortals()) { foreach (ZDO zdo in portal.Value) { if (PortalRecord.IsManagedPrefab(zdo.GetPrefab())) { found.Add(zdo); } } } if (ZNet.instance.IsServer()) { HashSet<ZDOID> ids = new HashSet<ZDOID>(); foreach (ZDO zdo2 in found) { ids.Add(zdo2.m_uid); if (Sent.Changed(zdo2.m_uid, zdo2.DataRevision, zdo2.OwnerRevision)) { ZDOMan.instance.ForceSendZDO(zdo2.m_uid); } } Sent.Prune(ids); } bool changed = found.Count != _portals.Count || !found.SetEquals(_portals); _portals = found; if (changed) { PortalRegistry.Changed?.Invoke(); } } yield return (object)new WaitForSeconds(5f); } } } [HarmonyPatch(typeof(Game), "Start")] internal static class Game_Start_ScanPortals { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(Game __instance) { PortalRegistry.Clear(); ((MonoBehaviour)__instance).StartCoroutine(PortalRegistry.Scan()); } } [HarmonyPatch(typeof(ZDOMan), "AddPeer")] internal static class ZDOMan_AddPeer_SendPortals { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(ZDOMan __instance, ZNetPeer netPeer) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } foreach (ZDO item in PortalRegistry.All) { __instance.ForceSendZDO(netPeer.m_uid, item.m_uid); } } } [HarmonyPatch(typeof(TeleportWorld), "Awake")] internal static class TeleportWorld_Awake_Register { [<596d02bc-cb07-4f28-80d1-942233a59b21>NullableContext(1)] private static void Postfix(TeleportWorld __instance, ZNetView ___m_nview) { if (ZNetView.m_forceDisableInit) { return; } if ((Object)(object)___m_nview == (Object)null) { return; } ZDO zdo = ___m_nview.GetZDO(); if (zdo == null || !PortalRecord.IsManagedPrefab(zdo.GetPrefab())) { return; } PortalRegistry.Add(zdo); WearNTear component = ((Component)__instance).GetComponent<WearNTear>(); if (!((Object)(object)component == (Object)null)) { Action previous = component