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 ProtectiveWards v2.1.0
ProtectiveWards.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Jotunn.GUI; using Jotunn.Managers; using Jotunn.Utils; using LocalizationManager; using Microsoft.CodeAnalysis; using ProtectiveWards; using ProtectiveWards.Compatibility; using SoftReferenceableAssets; using Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Protective Wards")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Protective Wards")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f71912b8-9b1c-4181-911a-1550f4ec2889")] [assembly: AssemblyFileVersion("2.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private const string defaultLanguage = "English"; private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts = new Dictionary<string, Dictionary<string, string>>(); private static readonly ConditionalWeakTable<Localization, string> localizationLanguage = new ConditionalWeakTable<Localization, string>(); private static readonly List<WeakReference<Localization>> localizationObjects = new List<WeakReference<Localization>>(); private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions = new List<string> { ".json", ".yml" }; private static bool initialized; private static bool localizationEnabled; 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((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out string value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2)) { text = value2.Aggregate(text, (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, Func<T, string>? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { 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 Initialize() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (!initialized) { initialized = true; if ((int)SystemInfo.graphicsDeviceType != 4) { EnsureYamlDotNetAvailable(); 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); localizationEnabled = true; } } } public static void ApplyCurrentLocalization() { if (!localizationEnabled || Localization.m_instance == null) { return; } string language = "English"; if (PlatformManager.DistributionPlatform != null && PlatformInitializer.PreferencesInitialized) { string selectedLanguage = Localization.m_instance.GetSelectedLanguage(); if (string.IsNullOrEmpty(selectedLanguage)) { PlatformPrefs.SetString("language", "English"); } else { language = selectedLanguage; } } LoadLocalization(Localization.m_instance, language); } private static void EnsureYamlDotNetAvailable() { try { if (Type.GetType("YamlDotNet.Serialization.DeserializerBuilder, YamlDotNet", throwOnError: false) != null) { return; } } catch (Exception innerException) { throw new FileNotFoundException("YamlDotNet is required for localization but could not be loaded. Install ValheimModding-YamlDotNet.", innerException); } throw new FileNotFoundException("YamlDotNet is required for localization but could not be loaded. Install ValheimModding-YamlDotNet."); } private static void LoadLocalization(Localization __instance, string language) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> localizationFiles = new Dictionary<string, string>(); string[] prefixes = new string[2] { Plugin.Info.Metadata.Name + ".", Plugin.Info.Metadata.Name.Replace(" ", "") + "." }; Scan(Paths.ConfigPath, warn: true); byte[] array = LoadTranslationFromAssembly("English"); if (array == 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> dictionary = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array)); if (dictionary == null) { throw new Exception("Localization for mod " + Plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text = null; if (language != "English") { if (localizationFiles.ContainsKey(language)) { text = File.ReadAllText(localizationFiles[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text = Encoding.UTF8.GetString(array2); } } } if (text == null && localizationFiles.ContainsKey("English")) { text = File.ReadAllText(localizationFiles["English"]); } if (text != null) { Dictionary<string, string> dictionary2; try { dictionary2 = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(); } catch (Exception arg) { global::ProtectiveWards.ProtectiveWards.LogInfo($"Failed to deserialize localization for language '{language}'. Using base localization only.\n{arg}"); dictionary2 = new Dictionary<string, string>(); } foreach (KeyValuePair<string, string> item in dictionary2) { dictionary[item.Key] = item.Value; } } loadedTexts[language] = dictionary; foreach (KeyValuePair<string, string> item2 in dictionary) { UpdatePlaceholderText(__instance, item2.Key); } void Scan(string root, bool warn) { foreach (string item3 in from f in Directory.GetFiles(root, "*.*", SearchOption.AllDirectories) where fileExtensions.Contains(Path.GetExtension(f)) select f) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item3); string[] array3 = prefixes; foreach (string text2 in array3) { if (fileNameWithoutExtension.StartsWith(text2)) { string text3 = fileNameWithoutExtension.Substring(text2.Length); if (!string.IsNullOrWhiteSpace(text3)) { if (localizationFiles.ContainsKey(text3)) { if (warn) { global::ProtectiveWards.ProtectiveWards.LogInfo("Duplicate localization '" + text3 + "' for " + Plugin.Info.Metadata.Name + ". Skipping " + item3); } } else { localizationFiles[text3] = item3; } } break; } } } } } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace ProtectiveWards { internal static class AdminServerFeatures { [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class Terminal_InitTerminal_RegisterCommands { private static void Postfix() { RegisterCommands(); } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_RegisterAdminRPCs { private static void Postfix() { RegisterRPCs(); } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_ResetAdminRPCs { private static void Postfix() { ResetRPCRegistration(); } } [HarmonyPatch(typeof(Piece), "SetCreator")] private static class Piece_SetCreator_CheckWardBuildLimit { private static void Postfix(Piece __instance, long uid) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (ProtectiveWards.wardBuildLimitPerPlayer.Value <= 0 || (Object)(object)__instance == (Object)null || uid == 0L || (Object)(object)((Component)__instance).GetComponent<PrivateArea>() == (Object)null || !WardZdoUtils.IsWardPrefab(((Component)__instance).gameObject)) { return; } ZNetView componentZNetView = ((Component)(object)__instance).GetComponentZNetView(); if ((Object)(object)componentZNetView == (Object)null || !componentZNetView.IsValid()) { return; } ZDO zDO = componentZNetView.GetZDO(); if (zDO != null) { ZDOID uid2 = zDO.m_uid; if (!s_requestedWardLimitChecks.Contains(uid2)) { s_requestedWardLimitChecks.Add(uid2); RequestWardBuildLimitCheck(uid, uid2); } } } } private const string RPC_CheckWardBuildLimit = "PW_CheckWardBuildLimit"; private const string RPC_DestroyWardForBuildLimit = "PW_DestroyWardForBuildLimit"; private static readonly HashSet<ZDOID> s_requestedWardLimitChecks = new HashSet<ZDOID>(); private static bool s_rpcRegistered; private static bool s_commandRegistered; internal static void RegisterRPCs() { if (!s_rpcRegistered && ZRoutedRpc.instance != null) { WardRpc.Register("PW_DestroyWardForBuildLimit", RPC_DestroyWardForBuildLimitClient); ZNet instance = ZNet.instance; if (instance != null && instance.IsServer()) { WardRpc.Register("PW_CheckWardBuildLimit", RPC_CheckWardBuildLimitServer); } s_rpcRegistered = true; } } internal static void ResetRPCRegistration() { s_rpcRegistered = false; s_requestedWardLimitChecks.Clear(); } private static void RegisterCommands() { if (!s_commandRegistered) { RegisterPlayerListCommand("pw_permit", "<player name> - add an online player to the nearest ward within configured range", RequestPermit); RegisterPlayerListCommand("ward_permit", "<player name> - add an online player to the nearest ward within configured range", RequestPermit); RegisterPlayerListCommand("pw_unpermit", "<player name> - remove a player from the nearest ward permitted list", RequestUnpermit); RegisterPlayerListCommand("ward_unpermit", "<player name> - remove a player from the nearest ward permitted list", RequestUnpermit); RegisterWardStateCommand("pw_enable", "enable the nearest ward within configured range", enabled: true); RegisterWardStateCommand("ward_enable", "enable the nearest ward within configured range", enabled: true); RegisterWardStateCommand("pw_disable", "disable the nearest ward within configured range", enabled: false); RegisterWardStateCommand("ward_disable", "disable the nearest ward within configured range", enabled: false); RegisterWardExpirationStateCommand("pw_set_expired", "mark the nearest ward as expired", expired: true); RegisterWardExpirationStateCommand("ward_set_expired", "mark the nearest ward as expired", expired: true); RegisterWardExpirationStateCommand("pw_set_unexpired", "clear expired state from the nearest ward", expired: false); RegisterWardExpirationStateCommand("ward_set_unexpired", "clear expired state from the nearest ward", expired: false); s_commandRegistered = true; } } private static void RegisterPlayerListCommand(string command, string description, Action<string, Terminal> action) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(command, description, (ConsoleEvent)delegate(ConsoleEventArgs args) { if (ValidateWardControlCommand(args.Context)) { if (args.Length < 2) { args.Context.AddString("Usage: <player name>"); } else { action(GetCommandQuery(args), args.Context); } } }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void RegisterWardStateCommand(string command, string description, bool enabled) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(command, description, (ConsoleEvent)delegate(ConsoleEventArgs args) { if (ValidateWardControlCommand(args.Context)) { RequestSetWardEnabled(enabled, args.Context); } }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void RegisterWardExpirationStateCommand(string command, string description, bool expired) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) new ConsoleCommand(command, description, (ConsoleEvent)delegate(ConsoleEventArgs args) { if (ValidateWardControlCommand(args.Context)) { RequestSetWardExpired(expired, args.Context); } }, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static string GetCommandQuery(ConsoleEventArgs args) { return string.Join(" ", args.Args.Skip(1).ToArray()).Trim(); } private static bool ValidateWardControlCommand(Terminal context) { if (AreWardControlCommandsEnabled()) { return true; } context.AddString("Ward control commands are disabled."); return false; } private static bool AreWardControlCommandsEnabled() { return ProtectiveWards.wardExternalControlCommandsEnabled.Value; } private static float GetWardControlCommandRange() { return Math.Max(ProtectiveWards.wardExternalControlCommandRange.Value, 0f); } private static void RequestPermit(string query, Terminal context) { RequestControl(WardControl.Operation.Permit, query, context); } private static void RequestUnpermit(string query, Terminal context) { RequestControl(WardControl.Operation.Unpermit, query, context); } private static void RequestSetWardEnabled(bool enabled, Terminal context) { RequestControl(enabled ? WardControl.Operation.Enable : WardControl.Operation.Disable, "", context); } private static void RequestSetWardExpired(bool expired, Terminal context) { RequestControl(expired ? WardControl.Operation.Expire : WardControl.Operation.Unexpire, "", context); } internal static void RequestPermittedWardToggle(PrivateArea ward, long playerID) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (ward == null) { return; } ZNetView nview = ward.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null && localPlayer.GetPlayerID() == playerID) { WardControl.Request(ward.m_nview.GetZDO().m_uid, WardControl.Operation.Toggle); } } } private static void RequestControl(WardControl.Operation action, string query, Terminal context) { //IL_00ea: 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_0081: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { context.AddString("Player is not available."); return; } PrivateArea val = null; float num = GetWardControlCommandRange(); foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (!ProtectiveWards.IsPlayerWardPrefab(allArea)) { continue; } ZNetView nview = allArea.m_nview; if (nview != null && nview.IsValid()) { float num2 = Utils.DistanceXZ(((Component)allArea).transform.position, ((Component)localPlayer).transform.position); if (num2 <= num) { num = num2; val = allArea; } } } if ((Object)(object)val == (Object)null) { context.AddString("$pw_permit_no_ward".Localize()); } else { WardControl.Request(val.m_nview.GetZDO().m_uid, action, query, context); } } private static void RequestWardBuildLimitCheck(long creatorID, ZDOID newWardID) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(creatorID); val.Write(newWardID); ZNet instance = ZNet.instance; if (instance != null && instance.IsServer()) { RPC_CheckWardBuildLimitServer(0L, new ZPackage(val.GetArray())); } else { WardRpc.SendToServer("PW_CheckWardBuildLimit", val); } } private static void RPC_CheckWardBuildLimitServer(long sender, ZPackage package) { //IL_0009: 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_0101: 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_006b: Unknown result type (might be due to invalid IL or missing references) long num = package.ReadLong(); ZDOID val = package.ReadZDOID(); try { if (ProtectiveWards.wardBuildLimitPerPlayer.Value <= 0 || num == 0L || ((ZDOID)(ref val)).Equals(ZDOID.None) || !ProtectiveWards.TryGetRoutedPlayer(sender, num, out var player)) { return; } ZDOMan instance = ZDOMan.instance; ZDO val2 = ((instance != null) ? instance.GetZDO(val) : null); if (val2.IsWard() && val2.IsCreator(player.PlayerID) && (sender == 0L || val2.GetOwner() == sender)) { int value = ProtectiveWards.wardBuildLimitPerPlayer.Value; int num2 = WardZdoUtils.CountWardsByCreator(player.PlayerID); if (num2 > value) { int current = Math.Max(num2 - 1, 0); SendDestroyWardForBuildLimit(val2, current, value); } } } finally { s_requestedWardLimitChecks.Remove(val); } } private static void SendDestroyWardForBuildLimit(ZDO zdo, int current, int limit) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown if (zdo != null) { ZDOID uid = zdo.m_uid; long owner = zdo.GetOwner(); DestroyWardForBuildLimitServer(zdo); ZPackage val = new ZPackage(); val.Write(uid); val.Write(current); val.Write(limit); if (owner != 0L && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(owner, "PW_DestroyWardForBuildLimit", new object[1] { val }); } else if ((Object)(object)Player.m_localPlayer != (Object)null) { RPC_DestroyWardForBuildLimitClient(0L, new ZPackage(val.GetArray())); } } } private static void DestroyWardForBuildLimitServer(ZDO zdo) { if (zdo != null && ZDOMan.instance != null) { zdo.SetOwner(ZDOMan.instance.m_sessionID); ZDOMan.instance.DestroyZDO(zdo); } } private static void RPC_DestroyWardForBuildLimitClient(long sender, ZPackage package) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (ProtectiveWards.IsServerRpcSender(sender)) { ZDOID wardID = package.ReadZDOID(); int num = package.ReadInt(); int num2 = package.ReadInt(); DestroyLocalWard(wardID); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "$pw_ward_limit_reached".Localize(num.ToString(), num2.ToString()), 0, (Sprite)null, false); } } } private static void DestroyLocalWard(ZDOID wardID) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject val = ZNetScene.instance.FindInstance(wardID); if ((Object)(object)val != (Object)null) { ZNetScene.instance.Destroy(val); } } } } internal static class WardRequestFlow { private sealed class Pending { internal string Request; internal string Result; internal ZDOID Ward; internal ZNetPeer Server; internal float Deadline; } private sealed class DispatchContext { internal long ID; internal long Sender; internal string Result; internal bool Replied; } [HarmonyPatch(typeof(Player), "Update")] private static class Player_Update_RequestTimeouts { private static void Postfix(Player __instance) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || s_pending.Count == 0) { return; } long[] array = (from pair in s_pending.Where(delegate(KeyValuePair<long, Pending> pair) { ZNetPeer server = pair.Value.Server; ZNet instance = ZNet.instance; return server != ((instance != null) ? instance.GetServerPeer() : null) || Time.realtimeSinceStartup >= pair.Value.Deadline; }) select pair.Key).ToArray(); foreach (long key in array) { if (s_pending.TryGetValue(key, out var value)) { s_pending.Remove(key); Recover(value.Ward); } } } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_ClearRequests { private static void Postfix() { s_pending.Clear(); s_dispatch.Clear(); } } private static readonly Dictionary<string, string> s_results = new Dictionary<string, string>(StringComparer.Ordinal) { ["PW_ApplyWardSettings"] = "PW_ApplyWardSettingsResult", ["PW_UpdateWardPassword"] = "PW_UpdateWardPasswordResult", ["PW_SubmitWardPassword"] = "PW_SubmitWardPasswordResult", ["PW_UpdateGuildBinding"] = "PW_UpdateGuildBindingResult", ["PW_UpdatePermittedPlayers"] = "PW_UpdatePermittedPlayersResult", ["PW_ReactivateExpiredWard"] = "PW_ReactivateExpiredWardResult" }; private static readonly Dictionary<long, Pending> s_pending = new Dictionary<long, Pending>(); private static readonly Stack<DispatchContext> s_dispatch = new Stack<DispatchContext>(); internal static bool TrySend(string method, ZPackage payload) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!s_results.TryGetValue(method, out var value)) { return false; } int pos = payload.GetPos(); payload.SetPos(0); ZDOID ward = payload.ReadZDOID(); payload.SetPos(pos); Cancel(method, ward); if (s_pending.Count < 32) { ZNet instance = ZNet.instance; if (((instance != null) ? instance.GetServerPeer() : null) != null) { long num = Utils.GenerateUID(); s_pending[num] = new Pending { Request = method, Result = value, Ward = ward, Server = ZNet.instance.GetServerPeer(), Deadline = Time.realtimeSinceStartup + 20f }; ZPackage val = new ZPackage(); val.Write(num); val.Write(payload); ZRoutedRpc.instance.InvokeRoutedRPC(method, new object[1] { val }); return true; } } Recover(ward); return true; } internal static void Dispatch(string method, long sender, ZPackage envelope, Action<long, ZPackage> handler) { //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (s_results.TryGetValue(method, out var value)) { ZNet instance = ZNet.instance; if (instance == null || !instance.IsServer()) { return; } long num = envelope.ReadLong(); ZPackage val = envelope.ReadPackage(); if (num == 0L || envelope.GetPos() != envelope.Size() || val.Size() > 65536) { return; } DispatchContext dispatchContext = new DispatchContext { ID = num, Sender = sender, Result = value }; s_dispatch.Push(dispatchContext); try { handler(sender, val); return; } finally { s_dispatch.Pop(); if (!dispatchContext.Replied) { Reply(dispatchContext, completed: false, new ZPackage()); } } } if (s_results.ContainsValue(method)) { if (!ProtectiveWards.IsServerRpcSender(sender)) { return; } long key = envelope.ReadLong(); bool flag = envelope.ReadBool(); ZPackage val2 = envelope.ReadPackage(); if (!s_pending.TryGetValue(key, out var value2) || value2.Result != method) { return; } ZNetPeer server = value2.Server; ZNet instance2 = ZNet.instance; if (server != ((instance2 != null) ? instance2.GetServerPeer() : null)) { return; } s_pending.Remove(key); if (flag && envelope.GetPos() == envelope.Size() && val2.Size() <= 65536) { try { handler(sender, val2); return; } catch { Recover(value2.Ward); throw; } } Recover(value2.Ward); } else { handler(sender, envelope); } } internal static bool TryReply(long peerID, string method, ZPackage payload) { if (s_dispatch.Count == 0) { return false; } DispatchContext dispatchContext = s_dispatch.Peek(); if (dispatchContext.Sender != peerID || dispatchContext.Result != method) { return false; } if (!dispatchContext.Replied) { Reply(dispatchContext, completed: true, payload); } return true; } private static void Reply(DispatchContext context, bool completed, ZPackage payload) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown context.Replied = true; ZPackage val = new ZPackage(); val.Write(context.ID); val.Write(completed); val.Write(payload); ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(context.Sender, context.Result, new object[1] { val }); } } internal static void Cancel(string method, ZDOID ward) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) long[] array = (from pair in s_pending where pair.Value.Request == method && pair.Value.Ward == ward select pair.Key).ToArray(); foreach (long key in array) { s_pending.Remove(key); } } private static void Recover(ZDOID ward) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) WardSettingsUI.CancelPendingNetworkOperation(ward); WardPermittedPlayersUI.CancelPendingNetworkOperation(ward); WardPasswordProtection.CancelPendingNetworkOperation(ward); if (!((ZDOID)(ref ward)).IsNone()) { ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.RequestZDO(ward); } } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Ward request outcome is unknown. Its state is being refreshed; reopen the ward before retrying.", 0, (Sprite)null, false); } } } internal static class WardControl { internal enum Operation { Permit, Unpermit, Enable, Disable, Expire, Unexpire, Toggle, ToggleSelfPermit } private sealed class PendingRequest { internal Terminal Console; internal Operation Action; internal float Deadline; } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_RegisterControl { private static void Postfix() { WardRpc.Register("PW_WardControlResultV2", HandleResult); ZNet instance = ZNet.instance; if (instance != null && instance.IsServer()) { WardRpc.Register("PW_WardControlV2", HandleRequest); } } } [HarmonyPatch(typeof(Player), "Update")] private static class Player_Update_ExpirePendingControl { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && s_pending.Count != 0) { long[] array = (from entry in s_pending where Time.realtimeSinceStartup >= entry.Value.Deadline select entry.Key).ToArray(); foreach (long key in array) { PendingRequest pendingRequest = s_pending[key]; s_pending.Remove(key); Report(pendingRequest.Console, "No ward response was received. The outcome is unknown; check the ward before retrying."); } } } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_ClearControl { private static void Postfix() { s_pending.Clear(); s_network = null; } } [HarmonyPatch(typeof(PrivateArea), "RPC_ToggleEnabled")] private static class PrivateArea_RPC_ToggleEnabled_RejectLegacyMutation { private static bool Prefix(PrivateArea __instance) { return !ProtectiveWards.IsPlayerWardPrefab(__instance); } } [HarmonyPatch(typeof(PrivateArea), "RPC_TogglePermitted")] private static class PrivateArea_RPC_TogglePermitted_RejectLegacyMutation { private static bool Prefix(PrivateArea __instance) { return !ProtectiveWards.IsPlayerWardPrefab(__instance); } } private const string RpcRequest = "PW_WardControlV2"; private const string RpcResult = "PW_WardControlResultV2"; private const int Protocol = 1; private static readonly Dictionary<long, PendingRequest> s_pending = new Dictionary<long, PendingRequest>(); private static ZNet s_network; internal static void Request(ZDOID wardID, Operation action, string query = "", Terminal console = null) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0094: 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_010b: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((ZDOID)(ref wardID)).IsNone() && !((Object)(object)ZNet.instance == (Object)null) && s_pending.Count < 32) { if ((Object)(object)s_network != (Object)(object)ZNet.instance) { s_pending.Clear(); s_network = ZNet.instance; } long num = Utils.GenerateUID(); ZPackage val = new ZPackage(); val.Write(1); val.Write(num); val.Write((int)action); val.Write(wardID); val.Write(localPlayer.GetPlayerID()); val.Write(query ?? ""); s_pending[num] = new PendingRequest { Console = console, Action = action, Deadline = Time.realtimeSinceStartup + 15f }; if (ZNet.instance.IsServer()) { HandleRequest(0L, new ZPackage(val.GetArray())); } else { WardRpc.SendToServer("PW_WardControlV2", val); } } } private static void HandleRequest(long sender, ZPackage package) { //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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) long num = 0L; Operation operation = Operation.Toggle; string message = "Ward request was rejected."; try { ZNet instance = ZNet.instance; if (instance == null || !instance.IsServer() || package.ReadInt() != 1) { return; } num = package.ReadLong(); operation = (Operation)package.ReadInt(); ZDOID zdoID = package.ReadZDOID(); long claimedPlayerID = package.ReadLong(); string text = package.ReadString().Trim(); if (!Enum.IsDefined(typeof(Operation), operation) || text.Length > 64 || package.GetPos() != package.Size()) { message = "Invalid ward control request."; return; } if (!ProtectiveWards.TryGetRoutedPlayer(sender, claimedPlayerID, out var player)) { message = "The requesting player is not available."; return; } ZDO ward = WardZdoUtils.GetWard(zdoID); if (ward == null) { message = "The ward is no longer available."; return; } bool flag = operation <= Operation.Unexpire; if (flag && !ProtectiveWards.wardExternalControlCommandsEnabled.Value) { message = "Ward control commands are disabled."; return; } float distance = (flag ? ProtectiveWards.wardExternalControlCommandRange.Value : 10f); if (!WardRpc.IsWithinReach(player, ward, distance, flag)) { message = "The ward is outside the allowed interaction range."; return; } bool flag2 = ward.IsCreator(player.PlayerID) || ProtectiveWards.HasWardManagementAccess(ward, player.PlayerID); if (!ProtectiveWards.HasWardManagementAccess(ward, player.PlayerID) && ProtectiveWards.ShouldBlockInactiveWardAccess(ward, player.PlayerID)) { message = "Another ward blocks access to this inactive ward."; return; } int num2; bool flag3; bool flag4; switch (operation) { case Operation.Permit: case Operation.Unpermit: if (!CanManageMembersByCommand(ward, player.PlayerID)) { message = "You do not have access to this ward."; return; } message = ChangeMember(ward, operation, text); break; case Operation.Toggle: num2 = (ProtectiveWards.CanPermittedPlayersToggleWard(ward, player.PlayerID) ? 1 : 0); goto IL_0226; case Operation.Enable: case Operation.Disable: num2 = 0; goto IL_0226; case Operation.Expire: case Operation.Unexpire: if (!ProtectiveWards.HasWardAdminAccess(player.PlayerID)) { message = "You are not allowed to change ward expiration."; return; } WardExpiration.SetExpired(ward, operation == Operation.Expire, player.PlayerID, player.PlayerName); message = ((operation == Operation.Expire) ? "Ward marked expired." : "Ward expiration cleared."); break; case Operation.ToggleSelfPermit: { if (ward.GetBool(ZDOVars.s_enabled, false) || (WardPasswordProtection.IsPasswordProtectionActive(ward) && !WardZdoUtils.HasDirectAccessToWardZdo(ward, player.PlayerID))) { message = "You cannot change your permission on this ward."; return; } if (WardZdoUtils.IsExplicitlyPermitted(ward, player.PlayerID)) { WardZdoUtils.RemovePermitted(ward, player.PlayerID, out var _); message = "You were removed from the ward's permitted list."; } else { WardZdoUtils.AddPermitted(ward, player.PlayerID, player.PlayerName); message = "You were added to the ward's permitted list."; } break; } IL_0226: flag3 = (byte)num2 != 0; if (!flag2 && !flag3) { message = "You are not allowed to toggle this ward."; return; } flag4 = ((operation == Operation.Toggle) ? (!ward.GetBool(ZDOVars.s_enabled, false)) : (operation == Operation.Enable)); if (ward.GetBool(ZDOVars.s_enabled, false) == flag4) { message = (flag4 ? "Ward is already enabled." : "Ward is already disabled."); return; } SetEnabled(ward, flag4); if (flag4 && flag2) { ProtectiveWards.ActivateConnectedWardZdos(ward, player.PlayerID, player.PlayerName); } message = (flag4 ? "Ward enabled." : "Ward disabled."); break; } WardZdoUtils.UpdateWardRuntimeFields(ward); PrivateArea val = WardZdoUtils.FindLoadedWard(zdoID); if ((Object)(object)val != (Object)null) { ProtectiveWards.RefreshWardVisuals(val); } } catch (Exception ex) { message = "The ward request could not be completed. Refresh its state before retrying."; Debug.LogWarning((object)("[ProtectiveWards] Ward control failed: " + ex.GetType().Name + ".")); } finally { if (num != 0) { SendResult(sender, num, operation, message); } } } private static bool CanManageMembersByCommand(ZDO ward, long playerID) { return WardZdoUtils.HasDirectAccessToWardZdo(ward, playerID) || (WardExpiration.IsWardActive(ward) && ward.HasConnectedWardAccess(playerID, ProtectiveWards.wardAccessConnectedAccessMode.Value, WardExpiration.IsWardActive)); } private static string ChangeMember(ZDO ward, Operation action, string query) { if (query.Length == 0) { return "Specify a player name."; } List<KeyValuePair<long, string>> list; if (action == Operation.Permit) { list = WardPlayers.FindByName(query); } else { List<KeyValuePair<long, string>> permittedPlayers = WardZdoUtils.GetPermittedPlayers(ward); list = permittedPlayers.Where((KeyValuePair<long, string> p) => string.Equals(p.Value, query, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count == 0) { list = permittedPlayers.Where((KeyValuePair<long, string> p) => p.Value.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0).ToList(); } } if (list.Count == 0) { return "No matching player was found."; } if (list.Count != 1) { return "More than one player matches. Use the exact name."; } KeyValuePair<long, string> keyValuePair = list[0]; if (action == Operation.Permit) { if (WardZdoUtils.IsExplicitlyPermitted(ward, keyValuePair.Key)) { return "The player is already permitted."; } WardZdoUtils.AddPermitted(ward, keyValuePair.Key, keyValuePair.Value); return "Added " + keyValuePair.Value + " to the ward's permitted list."; } WardZdoUtils.RemovePermitted(ward, keyValuePair.Key, out var _); return "Removed " + keyValuePair.Value + " from the ward's permitted list."; } private static void SetEnabled(ZDO ward, bool enabled) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) PrivateArea val = WardZdoUtils.FindLoadedWard(ward.m_uid); if ((Object)(object)val != (Object)null) { val.SetEnabled(enabled); } else { ward.Set(ZDOVars.s_enabled, enabled); } } private static void SendResult(long peerID, long requestID, Operation action, string message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(requestID); val.Write((int)action); val.Write(message); if (peerID == 0) { HandleResult(0L, new ZPackage(val.GetArray())); return; } ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(peerID, "PW_WardControlResultV2", new object[1] { val }); } } private static void HandleResult(long sender, ZPackage package) { if (ProtectiveWards.IsServerRpcSender(sender) && !((Object)(object)s_network != (Object)(object)ZNet.instance)) { long key = package.ReadLong(); Operation operation = (Operation)package.ReadInt(); string text = package.ReadString(); if (text.Length <= 1024 && package.GetPos() == package.Size() && s_pending.TryGetValue(key, out var value) && value.Action == operation) { s_pending.Remove(key); Report(value.Console, text); } } } private static void Report(Terminal console, string message) { if ((Object)(object)console != (Object)null) { console.AddString(message); return; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } } } internal static class WardPlayers { internal readonly struct OnlinePlayer { internal readonly long PlayerID; internal readonly ZDOID CharacterID; internal readonly string Name; internal readonly bool AdminAccess; internal OnlinePlayer(long playerID, ZDOID characterID, string name, bool adminAccess = false) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) PlayerID = playerID; CharacterID = characterID; Name = name ?? ""; AdminAccess = adminAccess; } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_RegisterRoster { private static void Postfix() { if (ZRoutedRpc.instance != null) { WardRpc.Register("PW_OnlinePlayerRoster", Receive); s_registered = true; Publish(); } } } [HarmonyPatch(typeof(ZNet), "SendPlayerList")] private static class ZNet_SendPlayerList_PublishRoster { private static void Postfix() { Publish(); } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_ClearRoster { private static void Postfix() { s_registered = false; s_remotePlayers.Clear(); } } private const string RpcRoster = "PW_OnlinePlayerRoster"; private const int MaximumPlayers = 512; private static readonly List<OnlinePlayer> s_remotePlayers = new List<OnlinePlayer>(); private static bool s_registered; internal static IEnumerable<OnlinePlayer> GetOnlinePlayers() { ZNet network = ZNet.instance; if ((Object)(object)network == (Object)null) { yield break; } Player local = Player.m_localPlayer; long localID = ((local != null) ? local.GetPlayerID() : 0); if (localID != 0) { yield return new OnlinePlayer(localID, ((Character)local).GetZDOID(), local.GetPlayerName()); } if (!network.IsServer()) { foreach (OnlinePlayer player in s_remotePlayers) { if (player.PlayerID != localID) { yield return player; } } yield break; } foreach (ZNetPeer peer in network.GetPeers()) { if (peer == null || !peer.IsReady() || peer.m_server || ((ZDOID)(ref peer.m_characterID)).IsNone()) { continue; } long playerID = peer.m_playerID; if (playerID == 0) { ZDOMan instance = ZDOMan.instance; long? obj; if (instance == null) { obj = null; } else { ZDO zDO = instance.GetZDO(peer.m_characterID); obj = ((zDO != null) ? new long?(zDO.GetLong(ZDOVars.s_playerID, 0L)) : ((long?)null)); } long? num = obj; playerID = num.GetValueOrDefault(); } if (playerID != 0L && playerID != localID) { yield return new OnlinePlayer(playerID, peer.m_characterID, peer.m_playerName); } } } internal static List<KeyValuePair<long, string>> FindByName(string query) { string normalized = (query ?? "").Trim(); if (normalized.Length == 0 || normalized.Length > 64) { return new List<KeyValuePair<long, string>>(); } List<KeyValuePair<long, string>> source = (from player in GetOnlinePlayers() group player by player.PlayerID into @group select new KeyValuePair<long, string>(@group.Key, @group.First().Name)).ToList(); List<KeyValuePair<long, string>> list = source.Where((KeyValuePair<long, string> player) => string.Equals(player.Value, normalized, StringComparison.OrdinalIgnoreCase)).ToList(); return (list.Count > 0) ? list : source.Where((KeyValuePair<long, string> player) => player.Value.IndexOf(normalized, StringComparison.OrdinalIgnoreCase) >= 0).ToList(); } internal static bool TryGet(long playerID, out OnlinePlayer result) { foreach (OnlinePlayer onlinePlayer in GetOnlinePlayers()) { if (onlinePlayer.PlayerID != playerID) { continue; } result = onlinePlayer; return true; } result = default(OnlinePlayer); return false; } internal static bool HasRemoteAdminAccess(long playerID) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return false; } foreach (OnlinePlayer s_remotePlayer in s_remotePlayers) { if (s_remotePlayer.PlayerID == playerID) { return s_remotePlayer.AdminAccess; } } return false; } private static void Publish() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if (!s_registered) { return; } ZNet instance = ZNet.instance; if (instance == null || !instance.IsServer()) { return; } List<OnlinePlayer> list = (from player in GetOnlinePlayers() group player by player.PlayerID into @group select @group.First()).Take(512).ToList(); ZPackage val = new ZPackage(); val.Write(list.Count); foreach (OnlinePlayer item in list) { val.Write(item.PlayerID); val.Write(item.CharacterID); val.Write((item.Name.Length > 64) ? item.Name.Substring(0, 64) : item.Name); val.Write(ProtectiveWards.HasWardAdminAccess(item.PlayerID)); } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null && peer.IsReady() && !peer.m_server) { ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "PW_OnlinePlayerRoster", new object[1] { val }); } } } private static void Receive(long sender, ZPackage package) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!ProtectiveWards.IsServerRpcSender(sender)) { return; } ZNet instance = ZNet.instance; if (instance == null || instance.IsServer()) { return; } int num = package.ReadInt(); if (num < 0 || num > 512) { return; } List<OnlinePlayer> list = new List<OnlinePlayer>(num); HashSet<long> hashSet = new HashSet<long>(); for (int i = 0; i < num; i++) { long num2 = package.ReadLong(); ZDOID characterID = package.ReadZDOID(); string text = package.ReadString(); bool adminAccess = package.ReadBool(); if (num2 == 0L || ((ZDOID)(ref characterID)).IsNone() || text.Length > 64 || !hashSet.Add(num2)) { return; } list.Add(new OnlinePlayer(num2, characterID, text, adminAccess)); } if (package.GetPos() == package.Size()) { s_remotePlayers.Clear(); s_remotePlayers.AddRange(list); } } } internal static class WardRpc { [HarmonyPatch(typeof(ZNet), "SendServerSyncPlayerData")] private static class ZNet_SendServerSyncPlayerData_AdminMode { private static void Prefix(ZNet __instance) { if (!__instance.IsServer()) { Dictionary<string, string> serverSyncedPlayerData = __instance.m_serverSyncedPlayerData; Player localPlayer = Player.m_localPlayer; serverSyncedPlayerData["pw_admin_god_mode"] = ((localPlayer != null && ((Character)localPlayer).InGodMode()) ? "1" : "0"); } } } [HarmonyPatch(typeof(Player), "SetGodMode")] private static class Player_SetGodMode_SynchronizeAdminMode { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { SyncLocalAdminMode(); } } } [HarmonyPatch(typeof(ZRoutedRpc), "RPC_RoutedRPC")] private static class ZRoutedRpc_RPC_RoutedRPC_ValidateWardSender { [HarmonyPriority(800)] private static bool Prefix(ZRpc rpc, ZPackage pkg) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (pkg == null || (Object)(object)ZNet.instance == (Object)null) { return true; } int pos = pkg.GetPos(); try { pkg.ReadLong(); long num = pkg.ReadLong(); pkg.ReadLong(); ZDOID val = pkg.ReadZDOID(); int num2 = pkg.ReadInt(); int num3; if (num2 == s_toggleEnabled || num2 == s_togglePermitted) { ZDOMan instance = ZDOMan.instance; num3 = (WardZdoUtils.IsWard((instance != null) ? instance.GetZDO(val) : null) ? 1 : 0); } else { num3 = 0; } bool flag = (byte)num3 != 0; if (!s_methods.Contains(num2) && !flag) { return true; } ZNet instance2 = ZNet.instance; ZNetPeer peer = instance2.GetPeer(rpc); bool flag2 = ((!instance2.IsServer()) ? (instance2.GetServerPeer()?.m_rpc == rpc) : (peer != null && peer.IsReady() && num == peer.m_uid)); if (!flag2) { WarnRejected("sender identity"); } return flag2; } catch (EndOfStreamException) { WarnRejected("truncated header"); return false; } finally { pkg.SetPos(pos); } } } private const string AdminGodModeKey = "pw_admin_god_mode"; private const int MaximumPackageBytes = 262144; private static readonly HashSet<int> s_methods = new HashSet<int> { StringExtensionMethods.GetStableHashCode("PW_GrowPlant"), StringExtensionMethods.GetStableHashCode("PW_AugmentStructure") }; private static readonly HashSet<int> s_registered = new HashSet<int>(); private static readonly int s_toggleEnabled = StringExtensionMethods.GetStableHashCode("ToggleEnabled"); private static readonly int s_togglePermitted = StringExtensionMethods.GetStableHashCode("TogglePermitted"); private static ZRoutedRpc s_router; private static ZNetPeer s_adminPeer; private static float s_nextWarning; internal static void Register(string name, Action<long, ZPackage> handler) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null || handler == null) { return; } if (s_router != instance) { s_router = instance; s_registered.Clear(); s_adminPeer = null; } int stableHashCode = StringExtensionMethods.GetStableHashCode(name); s_methods.Add(stableHashCode); if (!s_registered.Add(stableHashCode)) { return; } instance.Register<ZPackage>(name, (Action<long, ZPackage>)delegate(long sender, ZPackage package) { if (package == null || package.Size() > 262144) { WarnRejected(name); return; } try { WardRequestFlow.Dispatch(name, sender, package, handler); } catch (Exception ex) { Debug.LogWarning((object)("[ProtectiveWards] Request " + name + " failed: " + ex.GetType().Name + ".")); } }); } internal static void SendToServer(string name, ZPackage package) { SyncLocalAdminMode(); if (!WardRequestFlow.TrySend(name, package)) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(name, new object[1] { package }); } } } internal static void SendResponse(long peerID, string name, ZPackage package) { if (!WardRequestFlow.TryReply(peerID, name, package)) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(peerID, name, new object[1] { package }); } } } internal static bool HasRemoteGodMode(long playerID) { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || playerID == 0) { return false; } foreach (ZNetPeer peer in instance.GetPeers()) { if (peer == null || !peer.IsReady() || peer.m_playerID != playerID) { continue; } string value; return peer.m_serverSyncedPlayerData.TryGetValue("pw_admin_god_mode", out value) && value == "1"; } return false; } internal static void SyncLocalAdminMode() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { return; } ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { Player localPlayer = Player.m_localPlayer; string text = ((localPlayer != null && ((Character)localPlayer).InGodMode()) ? "1" : "0"); if (s_adminPeer != serverPeer || !instance.m_serverSyncedPlayerData.TryGetValue("pw_admin_god_mode", out var value) || !(value == text)) { s_adminPeer = serverPeer; instance.m_serverSyncedPlayerData["pw_admin_god_mode"] = text; instance.SendServerSyncPlayerData(serverPeer); } } } internal static bool IsWithinReach(ProtectiveWards.RoutedPlayerContext player, ZDO target, float distance = 10f, bool horizontal = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (target == null || !player.HasPosition || distance < 0f || float.IsNaN(distance) || float.IsInfinity(distance)) { return false; } Vector3 val = player.Position - target.GetPosition(); if (horizontal) { val.y = 0f; } return ((Vector3)(ref val)).sqrMagnitude <= distance * distance; } private static void WarnRejected(string method) { if (!(Time.realtimeSinceStartup < s_nextWarning)) { s_nextWarning = Time.realtimeSinceStartup + 5f; Debug.LogWarning((object)("[ProtectiveWards] Rejected invalid ward RPC (" + method + ").")); } } } internal static class ItemNameTokens { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDB_Awake_UpdateItemNameTokens { private static void Postfix() { UpdateRegisters(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static class ObjectDB_CopyOtherDB_UpdateItemNameTokens { private static void Postfix() { UpdateRegisters(); } } [HarmonyPatch(typeof(Player), "Load")] private static class Player_Load_UpdateItemNameTokens { private static void Prefix() { UpdateRegisters(); } } private static readonly Dictionary<string, string> s_itemNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); internal static void UpdateRegisters() { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } s_itemNames.Clear(); foreach (GameObject item in ObjectDB.instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (component != null) { SharedData val = component.m_itemData?.m_shared; if (val != null && !string.IsNullOrWhiteSpace(val.m_name) && val.m_name.StartsWith("$")) { Register(((Object)item).name, val.m_name); Register(val.m_name, val.m_name); Localization instance = Localization.instance; Register((instance != null) ? instance.Localize(val.m_name) : null, val.m_name); } } } } internal static string GetItemName(this string input) { if (string.IsNullOrWhiteSpace(input)) { return ""; } string text = input.Trim(); string value; return s_itemNames.TryGetValue(text, out value) ? value : text; } private static void Register(string key, string token) { if (!string.IsNullOrWhiteSpace(key)) { s_itemNames[key.Trim()] = token; } } } public static class StringExtensions { public static string Localize(this string text) { return (Localization.instance != null) ? Localization.instance.Localize(text) : text; } public static string Localize(this string text, params string[] words) { return (Localization.instance != null) ? Localization.instance.Localize(text, words) : text; } } internal static class ComponentExtensions { internal static bool IsVehicle(this Component component) { return (Object)(object)component != (Object)null && ((Object)(object)component.GetComponentInParent<Ship>() != (Object)null || (Object)(object)component.GetComponentInParent<Vagon>() != (Object)null); } internal static ZNetView GetComponentZNetView(this Component component) { if ((Object)(object)component == (Object)null) { return null; } PrivateArea val = (PrivateArea)(object)((component is PrivateArea) ? component : null); if (val != null) { return val.m_nview; } Ship val2 = (Ship)(object)((component is Ship) ? component : null); if (val2 != null) { return val2.m_nview; } ShipControlls val3 = (ShipControlls)(object)((component is ShipControlls) ? component : null); if (val3 != null) { return val3.m_nview; } Vagon val4 = (Vagon)(object)((component is Vagon) ? component : null); if (val4 != null) { return val4.m_nview; } Catapult val5 = (Catapult)(object)((component is Catapult) ? component : null); if (val5 != null) { return val5.m_nview; } MapTable val6 = (MapTable)(object)((component is MapTable) ? component : null); if (val6 != null) { return val6.m_nview; } Turret val7 = (Turret)(object)((component is Turret) ? component : null); if (val7 != null) { return val7.m_nview; } Fireplace val8 = (Fireplace)(object)((component is Fireplace) ? component : null); if (val8 != null) { return val8.m_nview; } Tameable val9 = (Tameable)(object)((component is Tameable) ? component : null); if (val9 != null) { return val9.m_nview; } Sadle val10 = (Sadle)(object)((component is Sadle) ? component : null); if (val10 != null) { return val10.m_nview; } TeleportWorld val11 = (TeleportWorld)(object)((component is TeleportWorld) ? component : null); if (val11 != null) { return val11.m_nview; } return component.GetComponent<ZNetView>() ?? component.GetComponentInParent<ZNetView>(); } internal static ZDO GetWardZDO(this Component component) { ZNetView componentZNetView = component.GetComponentZNetView(); return ((Object)(object)componentZNetView != (Object)null && componentZNetView.IsValid()) ? componentZNetView.GetZDO() : null; } } internal static class UIExtensions { internal static void KeepClickSfxOnly(this GameObject button) { ButtonSfx val = default(ButtonSfx); if ((Object)(object)button != (Object)null && button.TryGetComponent<ButtonSfx>(ref val)) { val.m_selectSfxPrefab = null; val.m_selectSfxPrefabVibrationOnly = null; } } } internal static class PrivateAreaExtensions { internal static ZDO GetWardZDO(this PrivateArea ward) { ZNetView componentZNetView = ((Component)(object)ward).GetComponentZNetView(); return ((Object)(object)componentZNetView != (Object)null && componentZNetView.IsValid()) ? componentZNetView.GetZDO() : null; } internal static bool HasDirectWardAccess(this PrivateArea ward, long playerID) { return ProtectiveWards.HasDirectAccessToWard(ward, playerID); } internal static bool HasConnectedWardAccess(this PrivateArea ward, long playerID, ProtectiveWards.WardConnectedAccessMode mode) { return ProtectiveWards.HasAccessToWardOrConnectedWard(ward, playerID, mode); } } internal static class WardZdoExtensions { internal static bool IsWard(this ZDO zdo) { return WardZdoUtils.IsWard(zdo); } internal static long GetCreatorId(this ZDO zdo) { return (zdo != null) ? zdo.GetLong(ZDOVars.s_creator, 0L) : 0; } internal static bool IsCreator(this ZDO zdo, long creatorID) { return zdo.GetCreatorId() == creatorID; } internal static bool HasDirectWardAccess(this ZDO zdo, long playerID) { return WardZdoUtils.HasDirectAccessToWardZdo(zdo, playerID); } internal static bool HasConnectedWardAccess(this ZDO zdo, long playerID, ProtectiveWards.WardConnectedAccessMode mode, Func<ZDO, bool> isActiveCandidate) { return WardZdoUtils.HasAccessToWardOrConnectedWardZdo(zdo, playerID, mode, isActiveCandidate); } internal static float GetWardRadius(this ZDO zdo) { return WardZdoUtils.GetWardRadius(zdo); } internal static bool IsWardPermitted(this ZDO zdo, long playerID) { return WardZdoUtils.IsPermitted(zdo, playerID); } } internal static class WardZdoUtils { private sealed class WardTraversal { internal readonly HashSet<ZDOID> Visited = new HashSet<ZDOID>(); internal readonly List<ZDO> Queue = new List<ZDO>(); internal readonly List<ZDO> Candidates = new List<ZDO>(); } [HarmonyPatch] private static class ZDOMan_Load_WardListInit { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(ZDOMan), "Load", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(ZDOMan), "LoadChunks", (Type[])null, (Type[])null); } private static void Postfix(ZDOMan __instance) { RebuildWardObjects(__instance); } } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_WardListInit { private static void Postfix() { EnsureWardObjectsInitialized(); UpdateAllWardRuntimeFields(); } } [HarmonyPatch(typeof(ZDOMan), "CreateNewZDO", new Type[] { typeof(ZDOID), typeof(Vector3), typeof(int) })] private static class ZDOMan_CreateNewZDO_WardListAddNew { private static void Postfix(int prefabHashIn, ZDO __result) { if (ShouldTrackServerWards() && (prefabHashIn == 0 || prefabHashIn == s_wardPrefabHash)) { AddIfWard(__result); } } } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] private static class ZDOMan_HandleDestroyedZDO_WardListRemove { private static void Prefix(ZDOMan __instance, ZDOID uid) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (__instance != null) { RemoveIfWard(__instance.GetZDO(uid)); } } } [HarmonyPatch(typeof(ZDO), "SetPrefab")] private static class ZDO_SetPrefab_WardListUpdate { private static void Postfix(ZDO __instance) { if (ShouldTrackServerWards()) { if (IsWard(__instance)) { s_wardObjects.Add(__instance); EnsureWardSettingsInitialized(__instance); } else { s_wardObjects.Remove(__instance); } } } } [HarmonyPatch(typeof(ZDO), "Deserialize")] private static class ZDO_Deserialize_WardListAdd { private static void Postfix(ZDO __instance) { AddIfWard(__instance); ProtectiveWards.NotifyWardZdoSynchronized(__instance); } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_WardListClear { private static void Postfix() { s_wardObjects.Clear(); s_wardObjectsInitialized = false; s_wardDefaultRadius = 32f; s_wardDefaultRadiusCached = false; } } [CompilerGenerated] private sealed class <ConnectedAccessWardZdos>d__46 : IEnumerable<ZDO>, IEnumerable, IEnumerator<ZDO>, IDisposable, IEnumerator { private int <>1__state; private ZDO <>2__current; private int <>l__initialThreadId; private ZDO rootWard; public ZDO <>3__rootWard; private ProtectiveWards.WardConnectedAccessMode mode; public ProtectiveWards.WardConnectedAccessMode <>3__mode; private Func<ZDO, bool> isActiveCandidate; public Func<ZDO, bool> <>3__isActiveCandidate; private WardTraversal <traversal>5__1; private int <queueIndex>5__2; private IEnumerator<ZDO> <>s__3; private ZDO <candidate>5__4; private ZDO <current>5__5; private List<ZDO>.Enumerator <>s__6; private ZDO <candidate>5__7; private bool <retain>5__8; ZDO IEnumerator<ZDO>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ConnectedAccessWardZdos>d__46(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } <traversal>5__1 = null; <>s__3 = null; <candidate>5__4 = null; <current>5__5 = null; <>s__6 = default(List<ZDO>.Enumerator); <candidate>5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!IsWard(rootWard)) { return false; } <>2__current = rootWard; <>1__state = 1; return true; case 1: <>1__state = -1; if (mode == ProtectiveWards.WardConnectedAccessMode.Off) { return false; } <traversal>5__1 = ((s_traversalPool.Count > 0) ? s_traversalPool.Pop() : new WardTraversal()); <>1__state = -3; <traversal>5__1.Visited.Add(rootWard.m_uid); <traversal>5__1.Queue.Add(rootWard); <>s__3 = GetAllWards().GetEnumerator(); try { while (<>s__3.MoveNext()) { <candidate>5__4 = <>s__3.Current; <traversal>5__1.Candidates.Add(<candidate>5__4); <candidate>5__4 = null; } } finally { if (<>s__3 != null) { <>s__3.Dispose(); } } <>s__3 = null; <queueIndex>5__2 = 0; goto IL_02f3; case 2: { <>1__state = -3; goto IL_01b6; } IL_02f3: if (<queueIndex>5__2 < <traversal>5__1.Queue.Count) { <current>5__5 = <traversal>5__1.Queue[<queueIndex>5__2++]; if (<queueIndex>5__2 > 1) { <>2__current = <current>5__5; <>1__state = 2; return true; } goto IL_01b6; } <>m__Finally1(); return false; IL_01b6: <>s__6 = <traversal>5__1.Candidates.GetEnumerator(); try { while (<>s__6.MoveNext()) { <candidate>5__7 = <>s__6.Current; if (IsWard(<candidate>5__7) && !<traversal>5__1.Visited.Contains(<candidate>5__7.m_uid) && (isActiveCandidate == null || isActiveCandidate(<candidate>5__7)) && AreWardZdosOverlapping(<current>5__5, <candidate>5__7) && CanShareConnectedWardAccess(rootWard, <candidate>5__7, mode)) { <traversal>5__1.Visited.Add(<candidate>5__7.m_uid); <traversal>5__1.Queue.Add(<candidate>5__7); <candidate>5__7 = null; } } } finally { ((IDisposable)<>s__6/*cast due to .constrained prefix*/).Dispose(); } <>s__6 = default(List<ZDO>.Enumerator); <current>5__5 = null; goto IL_02f3; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <retain>5__8 = <traversal>5__1.Candidates.Count <= 4096 && <traversal>5__1.Queue.Count <= 4096; <traversal>5__1.Visited.Clear(); <traversal>5__1.Queue.Clear(); <traversal>5__1.Candidates.Clear(); if (<retain>5__8 && s_traversalPool.Count < 4) { s_traversalPool.Push(<traversal>5__1); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<ZDO> IEnumerable<ZDO>.GetEnumerator() { <ConnectedAccessWardZdos>d__46 <ConnectedAccessWardZdos>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <ConnectedAccessWardZdos>d__ = this; } else { <ConnectedAccessWardZdos>d__ = new <ConnectedAccessWardZdos>d__46(0); } <ConnectedAccessWardZdos>d__.rootWard = <>3__rootWard; <ConnectedAccessWardZdos>d__.mode = <>3__mode; <ConnectedAccessWardZdos>d__.isActiveCandidate = <>3__isActiveCandidate; return <ConnectedAccessWardZdos>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<ZDO>)this).GetEnumerator(); } } internal const string WardPrefabName = "guard_stone"; internal static readonly int s_wardPrefabHash = StringExtensionMethods.GetStableHashCode("guard_stone"); private static readonly HashSet<ZDO> s_wardObjects = new HashSet<ZDO>(); private static bool s_wardObjectsInitialized; private static bool s_wardDefaultRadiusCached; private static float s_wardDefaultRadius = 32f; private const int MaximumPooledBuffers = 4; private const int MaximumRetainedEntries = 4096; private static readonly Stack<HashSet<ZDOID>> s_visitedPool = new Stack<HashSet<ZDOID>>(); private static readonly Stack<WardTraversal> s_traversalPool = new Stack<WardTraversal>(); private static readonly int[] s_permittedPlayerIdHashes = CreatePermittedPlayerIdHashes(); private const string HasFieldsKey = "HasFields"; private const string HasPrivateAreaFieldsKey = "HasFieldsPrivateArea"; internal const string PrivateAreaRadiusField = "PrivateArea.m_radius"; private const string PrivateAreaFlashAvailableField = "PrivateArea.m_flashAvailable"; private static int[] CreatePermittedPlayerIdHashes() { int[] array = new int[64]; for (int i = 0; i < array.Length; i++) { array[i] = StringExtensionMethods.GetStableHashCode("pu_id" + i); } return array; } internal static bool IsWardPrefab(GameObject gameObject) { return (Object)(object)gameObject != (Object)null && Utils.GetPrefabName(gameObject) == "guard_stone"; } internal static bool IsWard(ZDO zdo) { return zdo != null && zdo.GetPrefab() == s_wardPrefabHash; } internal static bool HasStoredWardSettings(ZDO zdo) { return IsWard(zdo) && zdo.GetInt(ProtectiveWards.s_wardSettingsVersion, 0) >= 1; } private static bool CanWriteWardZdo(ZDO zdo) { int result; if (IsWard(zdo)) { ZNet instance = ZNet.instance; result = ((instance != null && instance.IsServer()) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } internal static void EnsureWardSettingsInitialized(ZDO zdo) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) if (!CanWriteWardZdo(zdo)) { return; } if (!HasStoredWardSettings(zdo)) { bool flag = ProtectiveWards.HasZdoVec3(zdo, ProtectiveWards.s_color); if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_customRange)) { zdo.Set(ProtectiveWards.s_customRange, ProtectiveWards.HasZdoFloat(zdo, ProtectiveWards.s_range) || ProtectiveWards.setWardRange.Value); } if (!ProtectiveWards.HasZdoFloat(zdo, ProtectiveWards.s_range)) { zdo.Set(ProtectiveWards.s_range, ProtectiveWards.ClampWardRange(ProtectiveWards.wardRange.Value)); } if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_customColor)) { zdo.Set(ProtectiveWards.s_customColor, flag || ProtectiveWards.wardEmissionColorEnabled.Value); } if (!ProtectiveWards.HasZdoVec3(zdo, ProtectiveWards.s_color)) { zdo.Set(ProtectiveWards.s_color, new Vector3(ProtectiveWards.wardEmissionColor.Value.r, ProtectiveWards.wardEmissionColor.Value.g, ProtectiveWards.wardEmissionColor.Value.b)); } if (!ProtectiveWards.HasZdoFloat(zdo, ProtectiveWards.s_colorMultiplier)) { zdo.Set(ProtectiveWards.s_colorMultiplier, flag ? 1f : ProtectiveWards.wardEmissionColorMultiplier.Value); } if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_bubbleEnabled)) { zdo.Set(ProtectiveWards.s_bubbleEnabled, ProtectiveWards.wardBubbleShow.Value); } if (!ProtectiveWards.HasZdoVec3(zdo, ProtectiveWards.s_bubbleColor)) { zdo.Set(ProtectiveWards.s_bubbleColor, new Vector3(ProtectiveWards.wardBubbleColor.Value.r, ProtectiveWards.wardBubbleColor.Value.g, ProtectiveWards.wardBubbleColor.Value.b)); } if (!ProtectiveWards.HasZdoFloat(zdo, ProtectiveWards.s_bubbleColorAlpha)) { zdo.Set(ProtectiveWards.s_bubbleColorAlpha, ProtectiveWards.wardBubbleColor.Value.a); } SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleRefractionIntensity, ProtectiveWards.wardBubbleRefractionIntensity.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleWaveVel, ProtectiveWards.wardBubbleWaveIntensity.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleGlossiness, ProtectiveWards.wardBubbleGlossiness.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleMetallic, ProtectiveWards.wardBubbleMetallic.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleNormalScale, ProtectiveWards.wardBubbleNormalScale.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_bubbleDepthFade, ProtectiveWards.wardBubbleDepthFade.Value); if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_circleEnabled)) { zdo.Set(ProtectiveWards.s_circleEnabled, ProtectiveWards.wardAreaMarkerPatch.Value); } SetStringIfMissing(zdo, ProtectiveWards.s_circleStartColor, ColorUtility.ToHtmlStringRGBA(ProtectiveWards.wardAreaMarkerStartColor.Value)); SetStringIfMissing(zdo, ProtectiveWards.s_circleEndColor, ColorUtility.ToHtmlStringRGBA(ProtectiveWards.wardAreaMarkerEndColor.Value)); SetFloatIfMissing(zdo, ProtectiveWards.s_circleSpeed, ProtectiveWards.wardAreaMarkerSpeed.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_circleLength, ProtectiveWards.wardAreaMarkerLength.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_circleWidth, ProtectiveWards.wardAreaMarkerWidth.Value); SetFloatIfMissing(zdo, ProtectiveWards.s_circleAmount, ProtectiveWards.wardAreaMarkerAmount.Value); if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_permitEveryone)) { zdo.Set(ProtectiveWards.s_permitEveryone, ProtectiveWards.permitEveryone.Value); } if (!ProtectiveWards.HasZdoBool(zdo, ProtectiveWards.s_permittedPlayersCanToggle)) { zdo.Set(ProtectiveWards.s_permittedPlayersCanToggle, ProtectiveWards.wardPermittedPlayersCanToggle.Value); } zdo.Set(ProtectiveWards.s_wardSettingsVersion, 1, false); } UpdateWardRuntimeFields(zdo); } private static void SetFloatIfMissing(ZDO zdo, int key, float value) { if (!ProtectiveWards.HasZdoFloat(zdo, key)) { zdo.Set(key, value); } } private static void SetStringIfMissing(ZDO zdo, int key, string value) { if (!ProtectiveWards.HasZdoString(zdo, key)) { zdo.Set(key, value ?? string.Empty); } } internal static void UpdateWardRuntimeFields(ZDO zdo) { if (CanWriteWardZdo(zdo)) { zdo.Set("HasFields", true); zdo.Set("HasFieldsPrivateArea", true); zdo.Set("PrivateArea.m_radius", GetWardRadius(zdo)); zdo.Set("PrivateArea.m_flashAvailable", true); } } internal static void UpdateAllWardRuntimeFields() { ZDO[] array = GetAllWards().ToArray(); foreach (ZDO zdo in array) { EnsureWardSettingsInitialized(zdo); } } internal static IEnumerable<ZDO> GetAllWards() { if (ShouldTrackServerWards()) { EnsureWardObjectsInitialized(); PruneWardObjects(); foreach (ZDO s_wardObject in s_wardObjects) { yield return s_wardObject; } yield break; } HashSet<ZDOID> visited = ((s_visitedPool.Count > 0) ? s_visitedPool.Pop() : new HashSet<ZDOID>()); try { foreach (PrivateArea area in PrivateArea.m_allAreas) { int num; if (area == null) { num = 0; } else { ZNetView nview = area.m_nview; num = ((((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true) ? 1 : 0); } ZDO zdo = ((num != 0) ? area.m_nview.GetZDO() : null); if (IsWard(zdo) && visited.Add(zdo.m_uid)) { yield return zdo; } } } finally { bool retain = visited.Count <= 4096; visited.Clear(); if (retain && s_visitedPool.Count < 4) { s_visitedPool.Push(visited); } } } internal static bool TryFindActiveWardContainingPoint(Vector3 point, Func<ZDO, bool> isActive, out ZDO ward) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) ward = null; if (ShouldTrackServerWards()) { EnsureWardObjectsInitialized(); PruneWardObjects(); foreach (ZDO s_wardObject in s_wardObjects) { if (!isActive(s_wardObject) || !ProtectiveWards.IsInsideWardXZ(s_wardObject, point)) { continue; } ward = s_wardObject; return true; } return false; } foreach (PrivateArea allArea in PrivateArea.m_allAreas) { object obj; if (allArea != null) { ZNetView nview = allArea.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true) { obj = allArea.m_nview.GetZDO(); goto IL_00da; } } obj = null; goto IL_00da; IL_00da: ZDO val = (ZDO)obj; if (!IsWard(val) || !isActive(val) || !ProtectiveWards.IsInsideWardXZ(val, point)) { continue; } ward = val; return true; } return false; } internal static int CountWardsByCreator(long creatorID) { if (creatorID == 0) { return 0; } int num = 0; foreach (ZDO allWard in GetAllWards()) { if (allWard.IsCreator(creatorID)) { num++; } } return num; } internal static PrivateArea FindLoadedWard(ZDOID zdoID) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) foreach (PrivateArea allArea in PrivateArea.m_allAreas) { if (!((Object)(object)allArea == (Object)null) && !((Object)(object)allArea.m_nview == (Object)null) && allArea.m_nview.IsValid()) { ZDO zDO = allArea.m_nview.GetZDO(); if (zDO != null && ((ZDOID)(ref zDO.m_uid)).Equals(zdoID)) { return allArea; } } } return null; } internal static ZDO GetWard(ZDOID zdoID) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(zdoID) : null); return IsWard(val) ? val : null; } internal static bool TryGetWard(ZDOID zdoID, out ZDO zdo) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) zdo = GetWard(zdoID); return zdo != null; } internal static List<KeyValuePair<long, string>> GetPermittedPlayers(ZDO zdo) { List<KeyValuePair<long, string>> list = new List<KeyValuePair<long, string>>(); if (!IsWard(zdo)) { return list; } int num = Math.Max(zdo.GetInt(ZDOVars.s_permitted, 0), 0); for (int i = 0; i < num; i++) { long num2 = zdo.GetLong("pu_id" + i, 0L); if (num2 != 0) { list.Add(new KeyValuePair<long, string>(num2, zdo.GetString("pu_name" + i, ""))); } } return list; } internal static bool IsExplicitlyPermitted(ZDO zdo, long playerID) { if (playerID == 0L || !IsWard(zdo)) { return false; } int num = Math.Max(zdo.GetInt(ZDOVars.s_permitted, 0), 0); for (int i = 0; i < num; i++) { int num2 = ((i < s_permittedPlayerIdHashes.Length) ? s_permittedPlayerIdHashes[i] : StringExtensionMethods.GetStableHashCode("pu_id" + i)); if (zdo.GetLong(num2, 0L) == playerID) { return true; } } return false; } internal static bool AddPermitted(ZDO zdo, long playerID, string playerName) { if (!IsWard(zdo) || playerID == 0) { return false; } List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers(zdo); if (permittedPlayers.Any((KeyValuePair<long, string> player) => player.Key == playerID)) { return false; } permittedPlayers.Add(new KeyValuePair<long, string>(playerID, playerName ?? "")); SetPermittedPlayers(zdo, permittedPlayers); return true; } internal static bool RemovePermitted(ZDO zdo, long playerID, out string playerName) { playerName = ""; if (!IsWard(zdo) || playerID == 0) { return false; } List<KeyValuePair<long, string>> permittedPlayers = GetPermittedPlayers(zdo); KeyValuePair<long, string> keyValuePair = permittedPlayers.FirstOrDefault((KeyValuePair<long, string> player) => player.Key == playerID); if (keyValuePair.Key == 0) { return false; } playerName = keyValuePair.Value ?? ""; permittedPlayers.RemoveAll((KeyValuePair<long, string> player) => player.Key == playerID); SetPermittedPlayers(zdo, permittedPlayers); return true; } internal static void SetPermittedPlayers(ZDO zdo, List<KeyValuePair<long, string>> permitted) { if (IsWard(zdo)) { if (permitted == null) { permitted = new List<KeyValuePair<long, string>>(); } zdo.Set(ZDOVars.s_permitted, permitted.Count, false); for (int i = 0; i < permitted.Count; i++) { zdo.Set("pu_id" + i, permitted[i].Key); zdo.Set("pu_name" + i, permitted[i].Value ?? ""); } } } internal static bool IsPermitted(ZDO zdo, long playerID) { if (zdo == null || playerID == 0) { return false; } if (ProtectiveWards.HasWardManagementAccess(zdo, playerID)) { return true; } if (IsExplicitlyPermitted(zdo, playerID)) { return true; } return GuildsCompat.HasWardGuildAccess(zdo, playerID); } internal static bool HasDirectAccessToWardZdo(ZDO zdo, long playerID) { if (zdo == null) { return true; } if (playerID == 0) { return false; } if (!IsWard(zdo)) { return false; } if (zdo.IsCreator(playerID)) { return true; } return IsPermitted(zdo, playerID); } internal static bool UseCustomWardRange(ZDO zdo) { if (!ProtectiveWards.ArePerWardSettingsEnabled()) { return ProtectiveWards.setWardRange.Value; } if (zdo == null) { return false; } if (HasStoredWardSettings(zdo)) { return zdo.GetBool(ProtectiveWards.s_customRange, false); } return ProtectiveWards.HasZdoFloat(zdo, ProtectiveWards.s_range) || zdo.GetBool(ProtectiveWards.s_customRange, false); } internal static float GetConfiguredWardRange(ZDO zdo) { if (!ProtectiveWards.ArePerWardSettingsEnabled()) { return ProtectiveWards.ClampWardRange(ProtectiveWards.wardRange.Value); } if (zdo == null) { return GetWardDefaultRadius(); } return ProtectiveWards.ClampWardRange(zdo.GetFloat(ProtectiveWards.s_range, GetWardDefaultRadius())); } internal static float GetWardDefaultRadius() { if (s_wardDefaultRadiusCached) { return ProtectiveWards.ClampWardRange(s_wardDefaultRadius); } if ((Object)(object)ZNetScene.instance != (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab("guard_stone"); PrivateArea val = ((prefab != null) ? prefab.GetComponent<PrivateArea>() : null); if ((Object)(object)val != (Object)null) { s_wardDefaultRadius = val.m_radius; s_wardDefaultRadiusCached = true; } } return ProtectiveWards.ClampWardRange(s_wardDefaultRadius); } internal static float GetWardRadius(ZDO zdo) { if (zdo == null) { return GetWardDefaultRadius(); } float radius = default(float); if (ProtectiveWards.ArePerWardSettingsEnabled() && !HasStoredWardSettings(zdo) && zdo.GetFloat("PrivateArea.m_radius", ref radius)) { return ProtectiveWards.ClampWardRange(radius); } return UseCustomWardRange(zdo) ? GetConfiguredWardRange(zdo) : GetWardDefaultRadius(); } internal static bool AreWardZdosOverlapping(ZDO protectedWard, ZDO candidateWard) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!IsWard(protectedWard) || !IsWard(candidateWard)) { return false; } float wardRadius = GetWardRadius(protectedWard); float wardRadius2 = GetWardRadius(candidateWard); return ProtectiveWards.GetConfiguredWardDistance(protectedWard.GetPosition(), candidateWard.GetPosition()) <= wardRadius + wardRadius2; } internal static bool HasWardTrustAccess(ZDO ward, long playerID) { return IsWard(ward) && playerID != 0L && (ward.IsCreator(playerID) || ProtectiveWards.IsPermitEveryone(ward) || IsExplicitlyPermitted(ward, playerID) || GuildsCompat.HasWardGuildAccess(ward, playerID)); } internal static bool CanShareConnectedWardAccess(ZDO protectedWard, ZDO candidateWard, ProtectiveWards.WardConnectedAccessMode mode) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (mode == ProtectiveWards.WardConnectedAccessMode.Off) { return false; } if (!IsWard(protectedWard) || !IsWard(candidateWard)) { return false; } if (protectedWard == candidateWard || ((ZDOID)(ref protectedWard.m_uid)).Equals(candidateWard.m_uid)) { return true; } switch (mode) { case ProtectiveWards.WardConnectedAccessMode.SameCreatorOnly: { long creatorId = protectedWard.GetCreatorId(); long creatorId2 = candidateWard.GetCreatorId(); return creatorId != 0L && creatorId == creatorId2; } case ProtectiveWards.WardConnectedAccessMode.MutualTrust: { long creatorId = protectedWard.GetCreatorId(); long creatorId2 = candidateWard.GetCreatorId(); return creatorId != 0L && creatorId2 != 0L && HasWardTrustAccess(protectedWard, creatorId2) && HasWardTrustAccess(candidateWard, creatorId); } case ProtectiveWards.WardConnectedAccessMode.AnyConnected: return true; default: return false; } } internal static IEnumerable<ZDO> ConnectedAccessWardZdos(ZDO rootWard, ProtectiveWards.WardConnectedAccessMode mode, Func<ZDO, bool> isActiveCandidate) { if (!IsWard(rootWard)) { yield break; } yield return rootWard; if (mode == ProtectiveWards.WardConnectedAccessMode.Off) { yield break; } WardTraversal traversal = ((s_traversalPool.Count > 0) ? s_traversalPool.Pop() : new WardTraversal()); try { traversal.Visited.Add(rootWard.m_uid); traversal.Queue.Add(rootWard); foreach (ZDO candidate in GetAllWards()) { traversal.Candidates.Add(candidate); } int queueIndex = 0; while (queueIndex < traversal.Queue.Count) { ZDO current = traversal.Queue[queueIndex++]; if (queueIndex > 1) { yield return current; } foreach (ZDO candidate2 in traversal.Candidates) { if (IsWard(candidate2) && !traversal.Visited.Contains(candidate2.m_uid) && (isActiveCandidate == null || isActiveCandidate(candidate2)) && AreWardZdosOverlapping(current, candidate2) && CanShareConnectedWardAccess(rootWard, candidate2, mode)) { traversal.Visited.Add(candidate2.m_uid); traversal.Queue.Add(candidate2); } } } } finally { ((<ConnectedAccessWardZdos>d__46)/*Error near IL_0008: stateMachine*/).<retain>5__8 = traversal.Candidates.Count <= 4096 && traversal.Queue.Count <= 4096; traversal.Visited.Clear(); traversal.Queue.Clear(); traversal.Candidates.Clear(); bool retain = default(bool); if (retain && s_traversalPool.Count < 4) { s_traversalPool.Push(traversal); } } } internal static bool HasAccessToWardOrConnectedWardZdo(ZDO rootWard, long playerID, ProtectiveWards.WardConnectedAccessMode mode, Func<ZDO, bool> isActiveCandidate) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (HasDirectAccessToWardZdo(rootWard, playerID)) { return true; } if (mode == ProtectiveWards.WardConnectedAccessMode.Off) { return false; } foreach (ZDO item in ConnectedAccessWardZdos(rootWard, mode, isActiveCandidate)) { if (item == null || ((ZDOID)(ref item.m_uid)).Equals(rootWard.m_uid) || !HasDirectAccessToWardZdo(item, playerID)) { continue; } return true; } return false; } private static bool ShouldTrackServerWards() { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); } private static void AddIfWard(ZDO zdo) { if (ShouldTrackServerWards() && IsWard(zdo)) { s_wardObjects.Add(zdo); EnsureWardSettingsInitialized(zdo); } } private static void RemoveIfWard(ZDO zdo) { if (zdo != null && IsWard(zdo)) { s_wardObjects.Remove(zdo); } } private static void PruneWardObjects() { s_wardObjects.RemoveWhere((ZDO zdo) => zdo == null || !IsWard(zdo)); } private static void EnsureWardObjectsInitialized() { if (ShouldTrackServerWards()) { ZDOMan instance = ZDOMan.instance; if (instance != null && !s_wardObjectsInitialized) { RebuildWardObjects(instance); } } } private static void RebuildWardObjects(ZDOMan zdoMan) { s_wardObjects.Clear(); if (!ShouldTrackServerWards() || zdoMan == null) { s_wardObjectsInitialized = false; return; } s_wardObjectsInitialized = true; foreach (KeyValuePair<ZDOID, ZDO> item in zdoMan.m_objectsByID) { AddIfWard(item.Value); } } } internal static class BackgroundProtection { private struct CachedBool { public float Time; public bool Value; } [HarmonyPatch(typeof(ZoneSystem), "Start")] private static class ZoneSystem_Start_ResetBackgroundProtectionCache { private static void Postfix() { ResetCache(); } } [HarmonyPatch(typeof(ZoneSystem), "OnDestroy")] private static class ZoneSystem_OnDestroy_ResetBackgroundProtectionCache { private static void Postfix() { ResetCache(); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static class Player_TryPlacePiece_PreventBuildingWithoutPermittedPlayersNearby { [HarmonyPriority(800)] private static bool Prefix(Player __instance, Piece piece, ref bool __result) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)piece == (Object)null || (Object)(object)__instance.m_placementGhost == (Object)null) { return true; } if (!IsBuildingRestricted(__instance, __instance.m_placementGhost.transform.position)) { return true; } ((Character)__instance).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false); __result = false; return false; } } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] private static class Player_CheckCanRemovePiece_PreventDemolishingWithoutPermittedPlayersNearby { [HarmonyPriority(800)] private static bool Prefix(Player __instance, Piece piece, ref bool __result) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)piece == (Object)null) { return true; } if (piece.IsCreator()) { return true; } if (!IsBuildingRestricted(__instance, ((Component)piece).transform.position)) { return true; } ((Character)__instance).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null, false); __result = false; return false; } } [HarmonyPatch(typeof(WearNTear), "Damage")] private static class WearNTear_Damage_BackgroundProtection { private static void Prefix(WearNTear __instance, HitData hit) { if (!((Object)(object)__instance == (Object)null) && hit != null) { bool flag = (Object)(object)((Component)__instance).GetComponentInParent<Ship>() != (Object)null; bool flag2 = (Object)(object)((Component)__instance).GetComponentInParent<Vagon>() != (Object)null; if ((!ProtectiveWards.vehiclesNeverProtected.Value || !(flag || flag2)) && (ShouldSuppressWearNTearDamage(__instance, hit, flag, flag2) || ShouldSuppressTameDamageToStructure(__instance, hit))) { ((DamageTypes)(ref hit.m_damage)).Modify(0f); } } } } [HarmonyPatch(typeof(Character), "Damage")] private static class Character_Damage_BackgroundTameProtection { private static void Prefix(Character __instance, HitData hit) { if (ShouldSuppressTameCharacterDamage(__instance)) { ((Da