Decompiled source of STU Ward v1.0.1

STUWard.dll

Decompiled 2 hours ago
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 HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using STUWard;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
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: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("STUWard")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("STUWard")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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
{
	public static class Localizer
	{
		private static readonly string[] FileExtensions = new string[2] { ".json", ".yml" };

		private static readonly Dictionary<string, Dictionary<string, string>> CachedTranslations = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

		private static readonly IDeserializer Deserializer = new DeserializerBuilder().IgnoreFields().Build();

		private static BaseUnityPlugin? _plugin;

		private static bool _registeredWithJotunn;

		private static bool _hookedJotunn;

		private static string? _lastLoggedAppliedLanguage;

		private static int _lastLoggedAppliedCount = -1;

		private static BaseUnityPlugin Plugin
		{
			get
			{
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Expected O, but got Unknown
				if ((Object)(object)_plugin != (Object)null)
				{
					return _plugin;
				}
				IEnumerable<TypeInfo> source;
				try
				{
					source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
				}
				catch (ReflectionTypeLoadException ex)
				{
					source = from type in ex.Types
						where type != null
						select type.GetTypeInfo();
				}
				_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo type) => type.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(type)));
				return _plugin;
			}
		}

		private static CustomLocalization CustomLocalization => LocalizationManager.Instance.GetLocalization();

		public static event Action? OnLocalizationComplete;

		public static void Load()
		{
			_ = Plugin;
			LoadTranslations();
			RegisterWithJotunn();
			HookJotunn();
			ReloadCurrentLanguageIfAvailable();
			SafeCallLocalizeComplete();
		}

		public static void ReloadCurrentLanguageIfAvailable()
		{
			if (Localization.instance != null)
			{
				LoadTranslations();
				RegisterWithJotunn();
				ApplyCurrentLanguage(Localization.instance);
			}
		}

		public static void LoadLocalizationLater()
		{
			ReloadCurrentLanguageIfAvailable();
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		public static void AddText(string key, string text)
		{
			if (!CachedTranslations.TryGetValue("English", out Dictionary<string, string> value))
			{
				value = new Dictionary<string, string>(StringComparer.Ordinal);
				CachedTranslations["English"] = value;
			}
			value[key] = text;
			string text2 = "English";
			string text3 = key;
			CustomLocalization.ClearToken(ref text2, ref text3);
			CustomLocalization.AddTranslation(ref text2, ref text3, text);
			if (Localization.instance != null)
			{
				Localization.instance.AddWord(key, text);
			}
		}

		private static void LoadTranslations()
		{
			if (CachedTranslations.Count > 0)
			{
				return;
			}
			HashSet<string> availableLanguages = GetAvailableLanguages();
			Dictionary<string, string> dictionary = ReadMergedLanguage("English", null);
			if (dictionary == null || dictionary.Count == 0)
			{
				throw new InvalidOperationException("Found no English localizations in mod " + Plugin.Info.Metadata.Name + ". Expected translations/English.json or translations/English.yml.");
			}
			CachedTranslations["English"] = dictionary;
			foreach (string item in availableLanguages)
			{
				if (!item.Equals("English", StringComparison.OrdinalIgnoreCase))
				{
					Dictionary<string, string> dictionary2 = ReadMergedLanguage(item, dictionary);
					if (dictionary2 != null && dictionary2.Count > 0)
					{
						CachedTranslations[item] = dictionary2;
					}
				}
			}
			ManualLogSource log = STUWard.Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Loaded STUWard localizations: " + string.Join(", ", CachedTranslations.Select<KeyValuePair<string, Dictionary<string, string>>, string>((KeyValuePair<string, Dictionary<string, string>> kv) => $"{kv.Key}={kv.Value.Count}"))));
			}
		}

		private static void RegisterWithJotunn()
		{
			if (_registeredWithJotunn)
			{
				return;
			}
			_registeredWithJotunn = true;
			foreach (KeyValuePair<string, Dictionary<string, string>> cachedTranslation in CachedTranslations)
			{
				cachedTranslation.Deconstruct(out var key, out var value);
				string text = key;
				Dictionary<string, string> dictionary = value;
				Dictionary<string, string> dictionary2 = new Dictionary<string, string>(dictionary, StringComparer.Ordinal);
				CustomLocalization.AddTranslation(ref text, dictionary2);
			}
			ManualLogSource log = STUWard.Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Registered STUWard localizations with Jotunn: " + string.Join(", ", CachedTranslations.Keys)));
			}
		}

		private static void HookJotunn()
		{
			if (!_hookedJotunn)
			{
				LocalizationManager.OnLocalizationAdded += ReloadCurrentLanguageIfAvailable;
				_hookedJotunn = true;
			}
		}

		private static void ApplyCurrentLanguage(Localization localization)
		{
			string selectedLanguage = localization.GetSelectedLanguage();
			Dictionary<string, string> translationsForLanguage = GetTranslationsForLanguage(selectedLanguage);
			foreach (var (text3, text4) in translationsForLanguage)
			{
				localization.AddWord(text3, text4);
			}
			if (!string.Equals(_lastLoggedAppliedLanguage, selectedLanguage, StringComparison.Ordinal) || _lastLoggedAppliedCount != translationsForLanguage.Count)
			{
				_lastLoggedAppliedLanguage = selectedLanguage;
				_lastLoggedAppliedCount = translationsForLanguage.Count;
				ManualLogSource log = STUWard.Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Applied STUWard localization for language '{selectedLanguage}' with {translationsForLanguage.Count} entries.");
				}
			}
		}

		private static Dictionary<string, string> GetTranslationsForLanguage(string language)
		{
			if (CachedTranslations.TryGetValue(language, out Dictionary<string, string> value))
			{
				return value;
			}
			return CachedTranslations["English"];
		}

		private static HashSet<string> GetAvailableLanguages()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "English" };
			string[] manifestResourceNames = typeof(Localizer).Assembly.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				string[] fileExtensions = FileExtensions;
				foreach (string text2 in fileExtensions)
				{
					string text3 = "translations." + text2;
					if (!text.Contains(".translations.", StringComparison.OrdinalIgnoreCase) || !text.EndsWith(text2, StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					int num = text.LastIndexOf(".translations.", StringComparison.OrdinalIgnoreCase);
					if (num >= 0)
					{
						int num2 = num + ".translations.".Length;
						int num3 = text.Length - num2 - text2.Length;
						if (num3 > 0)
						{
							hashSet.Add(text.Substring(num2, num3));
						}
					}
				}
			}
			foreach (string item in from path in Directory.GetFiles(Paths.PluginPath, Plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where FileExtensions.Contains<string>(Path.GetExtension(path), StringComparer.OrdinalIgnoreCase)
				select path)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split('.');
				if (array.Length >= 2 && !string.IsNullOrWhiteSpace(array[1]))
				{
					hashSet.Add(array[1]);
				}
			}
			return hashSet;
		}

		private static Dictionary<string, string>? ReadMergedLanguage(string language, IReadOnlyDictionary<string, string>? englishFallback)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			if (englishFallback != null)
			{
				MergeInto(dictionary, englishFallback);
			}
			Dictionary<string, string> dictionary2 = ReadEmbeddedLanguage(language);
			if (dictionary2 != null)
			{
				MergeInto(dictionary, dictionary2);
			}
			Dictionary<string, string> dictionary3 = ReadExternalLanguage(language);
			if (dictionary3 != null)
			{
				MergeInto(dictionary, dictionary3);
			}
			return (dictionary.Count == 0) ? null : dictionary;
		}

		private static Dictionary<string, string>? ReadEmbeddedLanguage(string language)
		{
			string[] fileExtensions = FileExtensions;
			foreach (string text in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + text, typeof(Localizer).Assembly);
				if (array != null)
				{
					return DeserializeTranslations(Encoding.UTF8.GetString(array));
				}
			}
			return null;
		}

		private static Dictionary<string, string>? ReadExternalLanguage(string language)
		{
			string text = FindExternalLanguageFile(language);
			return (text == null) ? null : DeserializeTranslations(File.ReadAllText(text, Encoding.UTF8));
		}

		private static string? FindExternalLanguageFile(string language)
		{
			string[] fileExtensions = FileExtensions;
			foreach (string text in fileExtensions)
			{
				string searchPattern = Plugin.Info.Metadata.Name + "." + language + text;
				string text2 = Directory.GetFiles(Paths.PluginPath, searchPattern, SearchOption.AllDirectories).FirstOrDefault();
				if (!string.IsNullOrWhiteSpace(text2))
				{
					return text2;
				}
			}
			return null;
		}

		private static Dictionary<string, string> DeserializeTranslations(string rawText)
		{
			return Deserializer.Deserialize<Dictionary<string, string>>(rawText) ?? new Dictionary<string, string>(StringComparer.Ordinal);
		}

		private static void MergeInto(IDictionary<string, string> target, IReadOnlyDictionary<string, string> source)
		{
			foreach (KeyValuePair<string, string> item in source)
			{
				item.Deconstruct(out var key, out var value);
				string key2 = key;
				string value2 = value;
				target[key2] = value2;
			}
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			string resourceFileName2 = resourceFileName;
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(resourceFileName2, StringComparison.OrdinalIgnoreCase));
			if (text == null)
			{
				return null;
			}
			containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.1";
	}
}
namespace STUWard
{
	[BepInPlugin("sighsorry.STUWard", "STUWard", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal enum Toggle
		{
			Off,
			On
		}

		internal const string ModName = "STUWard";

		internal const string ModVersion = "1.0.1";

		internal const string Author = "sighsorry";

		internal const string ModGuid = "sighsorry.STUWard";

		private static readonly ConfigSync ConfigSync = new ConfigSync("sighsorry.STUWard")
		{
			DisplayName = "STUWard",
			CurrentVersion = "1.0.1",
			MinimumRequiredVersion = "1.0.1"
		};

		private Harmony _harmony = null;

		internal static ManualLogSource Log = null;

		internal static Plugin Instance = null;

		internal static WardGuiController WardGui = null;

		internal static ConfigEntry<Toggle> ServerConfigLocked = null;

		internal static ConfigEntry<string> BlockedItemPrefabs = null;

		internal static ConfigEntry<int> MaxWardsPerSteamId = null;

		internal static ConfigEntry<float> MaxWardRadius = null;

		internal static ConfigEntry<Toggle> DisableVanillaGuardStoneRecipe = null;

		internal static ConfigEntry<string> StuWardRecipe = null;

		internal static ConfigEntry<KeyboardShortcut> WardSettingsShortcut = null;

		private static HashSet<string> _blockedItemPrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private void Awake()
		{
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Localizer.Load();
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			ServerConfigLocked = BindConfig("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			ConfigSync.AddLockingConfigEntry<Toggle>(ServerConfigLocked);
			BlockedItemPrefabs = BindConfig("1 - General", "Blocked Item Prefabs", "kg_TameableCollector,PalStone,PalStoneSpeed,PalStoneArmour,PalStoneHeal", "Comma separated prefab names that cannot be equipped or used inside a foreign enabled guard stone area.");
			BlockedItemPrefabs.SettingChanged += delegate
			{
				RefreshBlockedItemPrefabs();
			};
			RefreshBlockedItemPrefabs();
			MaxWardsPerSteamId = BindConfig("1 - General", "Max Wards Per Steam ID", 3, "Maximum number of managed Wards allowed per Steam/platform account. Set to -1 for unlimited.");
			MaxWardRadius = BindConfig("1 - General", "Max Ward Radius", 32f, "Maximum configurable Ward radius. Valid range: 8 to 64.");
			MaxWardRadius.SettingChanged += delegate
			{
				WardSettings.HandleMaxRadiusChanged();
			};
			DisableVanillaGuardStoneRecipe = BindConfig("1 - General", "Disable Vanilla Guard Stone Recipe", Toggle.On, "If on, the vanilla guard_stone build recipe is removed from the Hammer piece table while STUWard remains available.");
			DisableVanillaGuardStoneRecipe.SettingChanged += delegate
			{
				ApplyRecipeSettings();
			};
			StuWardRecipe = BindConfig("1 - General", "STUWard Recipe", "GreydwarfEye:1,BoneFragments:3,Flint:5,Wood:7", "STUWard recipe override. Format: ItemPrefab:Amount[:Recover], ...");
			StuWardRecipe.SettingChanged += delegate
			{
				ApplyRecipeSettings();
			};
			WardSettingsShortcut = BindConfig<KeyboardShortcut>("2 - Client", "Ward Settings Shortcut", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Shortcut used to open the ward settings UI while looking at your ward. Example values: LeftAlt + E, F7", synchronizedSetting: false);
			WardGuiLayoutSettings.Bind();
			WardOwnership.Initialize();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterStuWardPiece;
			RegisterStuWardPiece();
			_harmony = new Harmony("sighsorry.STUWard");
			PatchHarmonySafely();
			WardGui = ((Component)this).gameObject.AddComponent<WardGuiController>();
			((BaseUnityPlugin)this).Config.Save();
			WardGuiLayoutSettings.CleanupLegacyConfigSection();
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterStuWardPiece;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Config.Save();
		}

		private void RegisterStuWardPiece()
		{
			StuWardPrefab.Register();
			ApplyRecipeSettings();
		}

		private void ApplyRecipeSettings()
		{
			StuWardPrefab.ApplyRecipeSettings();
		}

		private void PatchHarmonySafely()
		{
			TryPatchClass(typeof(PrivateAreaAwakePatch));
			TryPatchClass(typeof(PrivateAreaOnDestroyPatch));
			TryPatchClass(typeof(PrivateAreaUpdateStatusPatch));
			TryPatchClass(typeof(PrivateAreaIsInsidePatch));
			TryPatchClass(typeof(PrivateAreaShowAreaMarkerPatch));
			TryPatchClass(typeof(PrivateAreaGetHoverTextPatch));
			TryPatchClass(typeof(PrivateAreaHideMarkerPatch));
			TryPatchClass(typeof(PrivateAreaInteractAdminDebugPatch));
			TryPatchClass(typeof(PrivateAreaRpcToggleEnabledAdminDebugPatch));
			TryPatchClass(typeof(PrivateAreaRpcFlashShieldVolumePatch));
			TryPatchClass(typeof(PrivateAreaAddPermittedSnapshotPatch));
			TryPatchClass(typeof(PrivateAreaRemovePermittedSnapshotPatch));
			TryPatchClass(typeof(CircleProjectorCreateSegmentsPatch));
			TryPatchClass(typeof(DoorRpcUseDoorPatch));
			TryPatchClass(typeof(ZNetAwakeWardOwnershipPatch));
			TryPatchClass(typeof(PlayerStartWardOwnershipPatch));
			TryPatchClass(typeof(PlayerUpdateWardAdminDebugPatch));
			TryPatchClass(typeof(ObjectDBAwakePatch));
			TryPatchClass(typeof(ObjectDBCopyOtherDbPatch));
			TryPatchClass(typeof(DirectInteractionPatches));
			TryPatchClass(typeof(UseItemInteractionPatches));
			TryPatchClass(typeof(StationUsePatches));
			TryPatchClass(typeof(ProcessingInteractionPatches));
			TryPatchClass(typeof(TeleportWorldTeleportPatch));
			TryPatchClass(typeof(TeleportWorldTriggerPatch));
			TryPatchClass(typeof(ItemDropPickupPatch));
			TryPatchClass(typeof(HumanoidPickupPatch));
			TryPatchClass(typeof(PlayerTryPlacePiecePatch));
			TryPatchClass(typeof(PlayerSetupPlacementGhostPatch));
			TryPatchClass(typeof(PlayerUpdatePlacementGhostPatch));
			TryPatchClass(typeof(PlayerPlacePiecePatch));
			TryPatchClass(typeof(PlayerCheckCanRemovePiecePatch));
			TryPatchClass(typeof(PlayerRemovePiecePatch));
			TryPatchClass(typeof(PlayerRepairPatch));
			TryPatchClass(typeof(ZNetSceneDestroyPatch));
			TryPatchClass(typeof(PieceCanBeRemovedPatch));
			TryPatchClass(typeof(AttackSpawnOnHitTerrainPatch));
			TryPatchClass(typeof(TerrainOpAwakePatch));
			TryPatchClass(typeof(WearNTearDamagePatch));
			TryPatchClass(typeof(WearNTearRemovePatch));
			TryPatchClass(typeof(WearNTearRpcRemovePatch));
			TryPatchClass(typeof(DestructibleDamagePatch));
			TryPatchClass(typeof(TreeBaseDamagePatch));
			TryPatchClass(typeof(TreeBaseRpcDamagePatch));
			TryPatchClass(typeof(PlayerUseHotbarItemPatch));
			TryPatchClass(typeof(HumanoidUseItemPatch));
			TryPatchClass(typeof(HumanoidUpdateEquipmentPatch));
			TryPatchClass(typeof(HumanoidEquipItemPatch));
			TryPatchClass(typeof(HumanoidStartAttackPatch));
			TryPatchClass(typeof(AttackStartBlockedItemTargetPatch));
			TryPatchClass(typeof(InventoryGuiOnRightClickItemPatch));
			TryPatchClass(typeof(TameableCollectorCollectorItemPatch));
			TryPatchClass(typeof(AzuCraftyBoxesNearbyContainersPatch));
			TryPatchClass(typeof(PlayerAutoPickupPatch));
			TryPatchClass(typeof(TerminalTryRunCommandWardReportPatch));
			TryPatchOptionalCompat("TargetPortalCompat", delegate
			{
				TargetPortalCompat.TryPatch(_harmony);
			});
		}

		private void TryPatchClass(Type patchType)
		{
			try
			{
				_harmony.CreateClassProcessor(patchType).Patch();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to patch " + patchType.Name + ": " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private void TryPatchOptionalCompat(string name, Action patchAction)
		{
			try
			{
				patchAction();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to patch " + name + ": " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		internal static bool IsBlockedItem(string prefabName)
		{
			return !string.IsNullOrWhiteSpace(prefabName) && _blockedItemPrefabNames.Contains(prefabName);
		}

		internal static bool IsWardSettingsShortcutDown()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			int result;
			if (WardSettingsShortcut != null)
			{
				KeyboardShortcut value = WardSettingsShortcut.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					value = WardSettingsShortcut.Value;
					result = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0);
					goto IL_0031;
				}
			}
			result = 0;
			goto IL_0031;
			IL_0031:
			return (byte)result != 0;
		}

		internal static bool HasWardSettingsShortcutBinding()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			int result;
			if (WardSettingsShortcut != null)
			{
				KeyboardShortcut value = WardSettingsShortcut.Value;
				result = (((int)((KeyboardShortcut)(ref value)).MainKey > 0) ? 1 : 0);
			}
			else
			{
				result = 0;
			}
			return (byte)result != 0;
		}

		internal static string GetWardSettingsShortcutLabel()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (WardSettingsShortcut != null)
			{
				KeyboardShortcut value = WardSettingsShortcut.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
				{
					KeyboardShortcut value2 = WardSettingsShortcut.Value;
					List<string> list = new List<string>();
					AddModifierLabel(list, ((KeyboardShortcut)(ref value2)).Modifiers, (KeyCode)306, (KeyCode)305, "Ctrl");
					AddModifierLabel(list, ((KeyboardShortcut)(ref value2)).Modifiers, (KeyCode)308, (KeyCode)307, "Alt");
					AddModifierLabel(list, ((KeyboardShortcut)(ref value2)).Modifiers, (KeyCode)304, (KeyCode)303, "Shift");
					foreach (KeyCode modifier in ((KeyboardShortcut)(ref value2)).Modifiers)
					{
						if (modifier - 303 > 5)
						{
							list.Add(GetKeyLabel(modifier));
						}
					}
					list.Add(GetKeyLabel(((KeyboardShortcut)(ref value2)).MainKey));
					return string.Join("+", list);
				}
			}
			return WardLocalization.Localize("$stuw_shortcut_unbound", "Unbound");
		}

		private static void AddModifierLabel(List<string> parts, IEnumerable<KeyCode> modifiers, KeyCode left, KeyCode right, string label)
		{
			//IL_000c: 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_0013: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode modifier in modifiers)
			{
				if (modifier == left || modifier == right)
				{
					parts.Add(label);
					break;
				}
			}
		}

		private static string GetKeyLabel(KeyCode keyCode)
		{
			//IL_0005: 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_0036: Expected I4, but got Unknown
			//IL_0038: 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_005c: Expected I4, but got Unknown
			if (1 == 0)
			{
			}
			string result;
			switch (keyCode - 48)
			{
			default:
				switch (keyCode - 303)
				{
				case 4:
				case 5:
					result = "Alt";
					break;
				case 2:
				case 3:
					result = "Ctrl";
					break;
				case 0:
				case 1:
					result = "Shift";
					break;
				default:
					result = ((object)(KeyCode)(ref keyCode)).ToString();
					break;
				}
				break;
			case 0:
				result = "0";
				break;
			case 1:
				result = "1";
				break;
			case 2:
				result = "2";
				break;
			case 3:
				result = "3";
				break;
			case 4:
				result = "4";
				break;
			case 5:
				result = "5";
				break;
			case 6:
				result = "6";
				break;
			case 7:
				result = "7";
				break;
			case 8:
				result = "8";
				break;
			case 9:
				result = "9";
				break;
			}
			if (1 == 0)
			{
			}
			return result;
		}

		private void RefreshBlockedItemPrefabs()
		{
			_blockedItemPrefabNames = ParseCsv(BlockedItemPrefabs.Value);
		}

		private static HashSet<string> ParseCsv(string value)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrWhiteSpace(value))
			{
				return hashSet;
			}
			string[] array = value.Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = text.Trim();
				if (!string.IsNullOrWhiteSpace(text2))
				{
					hashSet.Add(text2);
				}
			}
			return hashSet;
		}

		internal static ConfigEntry<T> BindConfigEntry<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			return Instance.BindConfig(group, name, value, description, synchronizedSetting);
		}

		private ConfigEntry<T> BindConfig<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			string text = (synchronizedSetting ? "Synced with server." : "Not synced with server.");
			string text2 = (string.IsNullOrWhiteSpace(description) ? text : (description.TrimEnd() + " " + text));
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, new ConfigDescription(text2, (AcceptableValueBase)null, Array.Empty<object>()));
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val;
		}
	}
	[DisallowMultipleComponent]
	internal sealed class StuWardArea : MonoBehaviour
	{
		internal const string PrefabName = "piece_stuward";

		internal const string BasePrefabName = "guard_stone";

		internal const string DisplayName = "$stuw_piece_name";

		internal const string Description = "$stuw_piece_desc";

		internal static bool IsManaged(PrivateArea? area)
		{
			return (Object)(object)area != (Object)null && (Object)(object)((Component)area).GetComponent<StuWardArea>() != (Object)null;
		}
	}
	internal static class StuWardPrefab
	{
		private static bool _registered;

		private static GameObject? _stuWardPrefab;

		private static GameObject? _vanillaGuardStonePrefab;

		private static int _vanillaGuardStoneIndex = -1;

		private static Requirement[]? _defaultStuWardRequirements;

		internal static void Register()
		{
			//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_0061: 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_007a: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			if (_registered || PieceManager.Instance.GetPiece("piece_stuward") != null)
			{
				_registered = true;
			}
			else
			{
				if ((Object)(object)PrefabManager.Instance.GetPrefab("guard_stone") == (Object)null)
				{
					return;
				}
				PieceConfig val = new PieceConfig
				{
					PieceTable = "Hammer",
					Name = "$stuw_piece_name",
					Description = "$stuw_piece_desc"
				};
				CustomPiece val2 = new CustomPiece("piece_stuward", "guard_stone", val);
				GameObject piecePrefab = val2.PiecePrefab;
				Piece piece = val2.Piece;
				PrivateArea val3 = (((Object)(object)piecePrefab != (Object)null) ? piecePrefab.GetComponent<PrivateArea>() : null);
				if ((Object)(object)piecePrefab == (Object)null || (Object)(object)piece == (Object)null || (Object)(object)val3 == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Failed to create STUWard clone prefab from guard_stone.");
					return;
				}
				if ((Object)(object)piecePrefab.GetComponent<StuWardArea>() == (Object)null)
				{
					piecePrefab.AddComponent<StuWardArea>();
				}
				piece.m_name = "$stuw_piece_name";
				piece.m_description = "$stuw_piece_desc";
				piece.m_resources = CloneRequirements(piece.m_resources);
				val3.m_name = "$stuw_piece_name";
				val3.m_radius = 8f;
				if ((Object)(object)val3.m_areaMarker != (Object)null)
				{
					val3.m_areaMarker.m_radius = 8f;
				}
				_stuWardPrefab = piecePrefab;
				_defaultStuWardRequirements = CloneRequirements(piece.m_resources);
				PieceManager.Instance.AddPiece(val2);
				_registered = PieceManager.Instance.GetPiece("piece_stuward") != null;
				if (_registered)
				{
					Plugin.Log.LogInfo((object)"Registered STUWard clone piece.");
				}
			}
		}

		internal static void ApplyRecipeSettings()
		{
			ApplyVanillaGuardStoneRecipeSetting();
			ApplyStuWardRecipeSetting();
		}

		internal static void ApplyVanillaGuardStoneRecipeSetting()
		{
			PieceTable hammerPieceTable = GetHammerPieceTable();
			List<GameObject> list = hammerPieceTable?.m_pieces;
			GameObject prefab = PrefabManager.Instance.GetPrefab("guard_stone");
			if ((Object)(object)hammerPieceTable == (Object)null || list == null || (Object)(object)prefab == (Object)null)
			{
				return;
			}
			if (_vanillaGuardStonePrefab == null)
			{
				_vanillaGuardStonePrefab = prefab;
			}
			List<int> matchingGuardStoneIndexes = GetMatchingGuardStoneIndexes(list, prefab);
			if (_vanillaGuardStoneIndex < 0 && matchingGuardStoneIndexes.Count > 0)
			{
				_vanillaGuardStoneIndex = matchingGuardStoneIndexes[0];
			}
			if (Plugin.DisableVanillaGuardStoneRecipe != null && Plugin.DisableVanillaGuardStoneRecipe.Value == Plugin.Toggle.On)
			{
				for (int num = matchingGuardStoneIndexes.Count - 1; num >= 0; num--)
				{
					list.RemoveAt(matchingGuardStoneIndexes[num]);
				}
			}
			else if (matchingGuardStoneIndexes.Count == 0 && (Object)(object)_vanillaGuardStonePrefab != (Object)null)
			{
				int index = ((_vanillaGuardStoneIndex >= 0) ? Mathf.Clamp(_vanillaGuardStoneIndex, 0, list.Count) : list.Count);
				list.Insert(index, _vanillaGuardStonePrefab);
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				localPlayer.UpdateAvailablePiecesList();
			}
		}

		private static void ApplyStuWardRecipeSetting()
		{
			Piece val = (((Object)(object)_stuWardPrefab != (Object)null) ? _stuWardPrefab.GetComponent<Piece>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string text = Plugin.StuWardRecipe?.Value?.Trim() ?? string.Empty;
			Requirement[] requirements;
			if (string.IsNullOrWhiteSpace(text))
			{
				if (_defaultStuWardRequirements != null)
				{
					val.m_resources = CloneRequirements(_defaultStuWardRequirements);
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						localPlayer.UpdateAvailablePiecesList();
					}
				}
			}
			else if (!TryParseRequirements(text, out requirements))
			{
				Plugin.Log.LogWarning((object)("Invalid STUWard recipe override '" + text + "'. Keeping previous recipe."));
			}
			else
			{
				val.m_resources = requirements;
				Player localPlayer2 = Player.m_localPlayer;
				if (localPlayer2 != null)
				{
					localPlayer2.UpdateAvailablePiecesList();
				}
			}
		}

		private static PieceTable? GetHammerPieceTable()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("Hammer");
			return (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_buildPieces;
		}

		private static List<int> GetMatchingGuardStoneIndexes(List<GameObject> pieces, GameObject guardStonePrefab)
		{
			List<int> list = new List<int>();
			for (int i = 0; i < pieces.Count; i++)
			{
				GameObject val = pieces[i];
				if (!((Object)(object)val == (Object)null) && ((Object)(object)val == (Object)(object)guardStonePrefab || ((Object)val).name == "guard_stone"))
				{
					list.Add(i);
				}
			}
			return list;
		}

		private static Requirement[] CloneRequirements(Requirement[]? source)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (source == null || source.Length == 0)
			{
				return Array.Empty<Requirement>();
			}
			Requirement[] array = (Requirement[])(object)new Requirement[source.Length];
			for (int i = 0; i < source.Length; i++)
			{
				Requirement val = source[i];
				array[i] = new Requirement
				{
					m_resItem = val.m_resItem,
					m_amount = val.m_amount,
					m_extraAmountOnlyOneIngredient = val.m_extraAmountOnlyOneIngredient,
					m_amountPerLevel = val.m_amountPerLevel,
					m_recover = val.m_recover
				};
			}
			return array;
		}

		private static bool TryParseRequirements(string value, out Requirement[] requirements)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: 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_015d: Expected O, but got Unknown
			requirements = Array.Empty<Requirement>();
			string[] array = value.Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return false;
			}
			List<Requirement> list = new List<Requirement>(array.Length);
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Split(':');
				int num = array3.Length;
				if ((num < 2 || num > 3) ? true : false)
				{
					return false;
				}
				string text2 = array3[0].Trim();
				if (string.IsNullOrWhiteSpace(text2) || !int.TryParse(array3[1], out var result) || result <= 0)
				{
					return false;
				}
				GameObject val = ResolveItemPrefab(text2);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Unable to resolve STUWard recipe item prefab '" + text2 + "'."));
					return false;
				}
				bool result2 = true;
				if (array3.Length == 3 && !TryParseBool(array3[2], out result2))
				{
					return false;
				}
				list.Add(new Requirement
				{
					m_resItem = val2,
					m_amount = result,
					m_amountPerLevel = 1,
					m_recover = result2
				});
			}
			requirements = list.ToArray();
			return true;
		}

		private static GameObject? ResolveItemPrefab(string prefabName)
		{
			if (string.IsNullOrWhiteSpace(prefabName))
			{
				return null;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return PrefabManager.Instance.GetPrefab(prefabName);
		}

		private static bool TryParseBool(string value, out bool result)
		{
			switch (value.Trim().ToLowerInvariant())
			{
			case "1":
			case "true":
			case "yes":
			case "on":
				result = true;
				return true;
			case "0":
			case "false":
			case "no":
			case "off":
				result = false;
				return true;
			default:
				result = false;
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDBAwakePatch
	{
		private static void Postfix()
		{
			Localizer.ReloadCurrentLanguageIfAvailable();
			StuWardPrefab.ApplyRecipeSettings();
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDBCopyOtherDbPatch
	{
		private static void Postfix()
		{
			Localizer.ReloadCurrentLanguageIfAvailable();
			StuWardPrefab.ApplyRecipeSettings();
		}
	}
	internal readonly struct WardGuildIdentity
	{
		internal int Id { get; }

		internal string Name { get; }

		internal WardGuildIdentity(int id, string name)
		{
			Id = id;
			Name = name;
		}
	}
	internal readonly struct CachedWardGuildIdentity
	{
		internal bool HasGuild { get; }

		internal int GuildId { get; }

		internal string GuildName { get; }

		internal DateTime ExpiresAtUtc { get; }

		internal CachedWardGuildIdentity(bool hasGuild, int guildId, string guildName, DateTime expiresAtUtc)
		{
			HasGuild = hasGuild;
			GuildId = guildId;
			GuildName = guildName;
			ExpiresAtUtc = expiresAtUtc;
		}
	}
	internal static class GuildsCompat
	{
		private const string GuildIdKey = "stuw_guild_id";

		private const string GuildNameKey = "stuw_guild_name";

		private const string GuildsPluginGuid = "org.bepinex.plugins.guilds";

		private static readonly TimeSpan GuildLookupCacheDuration = TimeSpan.FromSeconds(5.0);

		private static readonly Assembly? GuildsAssembly = GetPluginAssembly("org.bepinex.plugins.guilds");

		private static readonly Type? ApiType = GuildsAssembly?.GetType("Guilds.API");

		private static readonly Type? GuildType = GuildsAssembly?.GetType("Guilds.Guild");

		private static readonly Type? GuildGeneralType = GuildsAssembly?.GetType("Guilds.GuildGeneral");

		private static readonly Type? PlayerReferenceType = GuildsAssembly?.GetType("Guilds.PlayerReference");

		private static readonly MethodInfo? IsLoadedMethod = ((ApiType != null) ? AccessTools.Method(ApiType, "IsLoaded", (Type[])null, (Type[])null) : null);

		private static readonly MethodInfo? GetPlayerGuildByPlayerMethod = ((ApiType != null) ? AccessTools.Method(ApiType, "GetPlayerGuild", new Type[1] { typeof(Player) }, (Type[])null) : null);

		private static readonly MethodInfo? GetPlayerGuildByReferenceMethod = ((ApiType != null && PlayerReferenceType != null) ? AccessTools.Method(ApiType, "GetPlayerGuild", new Type[1] { PlayerReferenceType }, (Type[])null) : null);

		private static readonly MethodInfo? PlayerReferenceFromPlayerInfoMethod = ((PlayerReferenceType != null) ? AccessTools.Method(PlayerReferenceType, "fromPlayerInfo", new Type[1] { typeof(PlayerInfo) }, (Type[])null) : null);

		private static readonly FieldInfo? PlayerInfoUserInfoField = AccessTools.Field(typeof(PlayerInfo), "m_userInfo");

		private static readonly FieldInfo? UserInfoIdField = ((PlayerInfoUserInfoField?.FieldType != null) ? AccessTools.Field(PlayerInfoUserInfoField.FieldType, "m_id") : null);

		private static readonly FieldInfo? GuildNameField = ((GuildType != null) ? AccessTools.Field(GuildType, "Name") : null);

		private static readonly FieldInfo? GuildGeneralField = ((GuildType != null) ? AccessTools.Field(GuildType, "General") : null);

		private static readonly FieldInfo? GuildGeneralIdField = ((GuildGeneralType != null) ? AccessTools.Field(GuildGeneralType, "id") : null);

		private static readonly Dictionary<long, CachedWardGuildIdentity> PlayerGuildCache = new Dictionary<long, CachedWardGuildIdentity>();

		private static Assembly? GetPluginAssembly(string pluginGuid)
		{
			if (!Chainloader.PluginInfos.TryGetValue(pluginGuid, out var value))
			{
				return null;
			}
			return ((object)value.Instance)?.GetType().Assembly;
		}

		internal static bool IsAvailable()
		{
			if (ApiType == null || IsLoadedMethod == null)
			{
				return false;
			}
			try
			{
				return (IsLoadedMethod.Invoke(null, Array.Empty<object>()) as bool?).GetValueOrDefault();
			}
			catch
			{
				return false;
			}
		}

		internal static void OnZNetAwake()
		{
			PlayerGuildCache.Clear();
		}

		internal static void TryAssignWardGuild(PrivateArea area, Player? player)
		{
			if (IsAvailable() && !((Object)(object)area == (Object)null) && !((Object)(object)player == (Object)null))
			{
				ZNetView nview = area.m_nview;
				object obj = ((nview != null) ? nview.GetZDO() : null);
				if (obj == null)
				{
					ZNetView component = ((Component)area).GetComponent<ZNetView>();
					obj = ((component != null) ? component.GetZDO() : null);
				}
				ZDO val = (ZDO)obj;
				if (val != null && val.GetInt("stuw_guild_id", 0) == 0 && WardAccess.GetWardOwnerId(area) == player.GetPlayerID() && TryGetGuild(player, out var guild))
				{
					val.Set("stuw_guild_id", guild.Id);
					val.Set("stuw_guild_name", guild.Name ?? string.Empty);
				}
			}
		}

		internal static int GetWardGuildId(PrivateArea? area)
		{
			object obj;
			if (area == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = area.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			if (obj == null)
			{
				if (area == null)
				{
					obj = null;
				}
				else
				{
					ZNetView component = ((Component)area).GetComponent<ZNetView>();
					obj = ((component != null) ? component.GetZDO() : null);
				}
			}
			ZDO val = (ZDO)obj;
			return (val != null) ? val.GetInt("stuw_guild_id", 0) : 0;
		}

		internal static string GetWardGuildName(PrivateArea? area)
		{
			object obj;
			if (area == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = area.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			if (obj == null)
			{
				if (area == null)
				{
					obj = null;
				}
				else
				{
					ZNetView component = ((Component)area).GetComponent<ZNetView>();
					obj = ((component != null) ? component.GetZDO() : null);
				}
			}
			ZDO val = (ZDO)obj;
			return ((val != null) ? val.GetString("stuw_guild_name", string.Empty) : null) ?? string.Empty;
		}

		internal static int GetPlayerGuildId(Player? player)
		{
			WardGuildIdentity guild;
			return TryGetGuild(player, out guild) ? guild.Id : 0;
		}

		internal static string GetPlayerGuildName(long playerId)
		{
			WardGuildIdentity guild;
			return TryGetGuild(playerId, out guild) ? guild.Name : string.Empty;
		}

		internal static string GetPlayerPlatformId(long playerId)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			PlayerInfo? val = FindPlayerInfo(playerId);
			if (!val.HasValue || PlayerInfoUserInfoField == null || UserInfoIdField == null)
			{
				return string.Empty;
			}
			try
			{
				object obj = val.Value;
				object value = PlayerInfoUserInfoField.GetValue(obj);
				if (value == null)
				{
					return string.Empty;
				}
				return UserInfoIdField.GetValue(value)?.ToString() ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		internal static bool PlayerMatchesWardGuild(Player? player, PrivateArea? area)
		{
			if (!TryGetGuild(player, out var guild))
			{
				return false;
			}
			int wardGuildId = GetWardGuildId(area);
			return wardGuildId != 0 && wardGuildId == guild.Id;
		}

		internal static bool PlayerIdMatchesWardGuild(long playerId, PrivateArea? area)
		{
			int wardGuildId = GetWardGuildId(area);
			if (playerId == 0L || wardGuildId == 0 || !TryGetGuild(playerId, out var guild))
			{
				return false;
			}
			return wardGuildId == guild.Id;
		}

		private static bool TryGetGuild(Player? player, out WardGuildIdentity guild)
		{
			guild = default(WardGuildIdentity);
			if (!IsAvailable() || (Object)(object)player == (Object)null || GetPlayerGuildByPlayerMethod == null)
			{
				return false;
			}
			try
			{
				object guildObject = GetPlayerGuildByPlayerMethod.Invoke(null, new object[1] { player });
				bool flag = TryParseGuild(guildObject, out guild);
				CacheGuildLookup(player.GetPlayerID(), flag, guild);
				return flag;
			}
			catch
			{
				CacheGuildLookup(player.GetPlayerID(), hasGuild: false, default(WardGuildIdentity));
				return false;
			}
		}

		private static bool TryGetGuild(long playerId, out WardGuildIdentity guild)
		{
			guild = default(WardGuildIdentity);
			if (!IsAvailable() || playerId == 0)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && localPlayer.GetPlayerID() == playerId)
			{
				return TryGetGuild(localPlayer, out guild);
			}
			if (TryGetCachedGuild(playerId, out guild))
			{
				return true;
			}
			if (IsCachedNoGuild(playerId))
			{
				return false;
			}
			if (GetPlayerGuildByReferenceMethod == null || PlayerReferenceFromPlayerInfoMethod == null)
			{
				return false;
			}
			PlayerInfo? val = FindPlayerInfo(playerId);
			if (!val.HasValue)
			{
				CacheGuildLookup(playerId, hasGuild: false, default(WardGuildIdentity));
				return false;
			}
			try
			{
				object obj = PlayerReferenceFromPlayerInfoMethod.Invoke(null, new object[1] { val });
				object guildObject = GetPlayerGuildByReferenceMethod.Invoke(null, new object[1] { obj });
				bool flag = TryParseGuild(guildObject, out guild);
				CacheGuildLookup(playerId, flag, guild);
				return flag;
			}
			catch
			{
				CacheGuildLookup(playerId, hasGuild: false, default(WardGuildIdentity));
				return false;
			}
		}

		private static bool TryGetCachedGuild(long playerId, out WardGuildIdentity guild)
		{
			guild = default(WardGuildIdentity);
			if (!PlayerGuildCache.TryGetValue(playerId, out var value))
			{
				return false;
			}
			if (value.ExpiresAtUtc <= DateTime.UtcNow)
			{
				PlayerGuildCache.Remove(playerId);
				return false;
			}
			if (!value.HasGuild || value.GuildId == 0)
			{
				return false;
			}
			guild = new WardGuildIdentity(value.GuildId, value.GuildName);
			return true;
		}

		private static bool IsCachedNoGuild(long playerId)
		{
			if (!PlayerGuildCache.TryGetValue(playerId, out var value))
			{
				return false;
			}
			if (value.ExpiresAtUtc <= DateTime.UtcNow)
			{
				PlayerGuildCache.Remove(playerId);
				return false;
			}
			return !value.HasGuild;
		}

		private static void CacheGuildLookup(long playerId, bool hasGuild, WardGuildIdentity guild)
		{
			if (playerId != 0)
			{
				PlayerGuildCache[playerId] = new CachedWardGuildIdentity(hasGuild && guild.Id != 0, guild.Id, guild.Name ?? string.Empty, DateTime.UtcNow + GuildLookupCacheDuration);
			}
		}

		private static PlayerInfo? FindPlayerInfo(long playerId)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerInfo> list = ZNet.instance?.m_players;
			if (list == null)
			{
				return null;
			}
			for (int i = 0; i < list.Count; i++)
			{
				PlayerInfo val = list[i];
				ZDOMan instance = ZDOMan.instance;
				ZDO val2 = ((instance != null) ? instance.GetZDO(val.m_characterID) : null);
				if (((val2 != null) ? val2.GetLong(ZDOVars.s_playerID, 0L) : 0) == playerId)
				{
					return val;
				}
			}
			return null;
		}

		private static bool TryParseGuild(object? guildObject, out WardGuildIdentity guild)
		{
			guild = default(WardGuildIdentity);
			if (guildObject == null || GuildNameField == null || GuildGeneralField == null || GuildGeneralIdField == null)
			{
				return false;
			}
			try
			{
				object value = GuildGeneralField.GetValue(guildObject);
				int num = ((value != null) ? Convert.ToInt32(GuildGeneralIdField.GetValue(value)) : 0);
				if (num == 0)
				{
					return false;
				}
				string name = (GuildNameField.GetValue(guildObject) as string) ?? string.Empty;
				guild = new WardGuildIdentity(num, name);
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	internal static class WardAccess
	{
		private const string NoAccessMessageKey = "$piece_noaccess";

		private static readonly List<PrivateArea> ManagedWards = new List<PrivateArea>();

		private static readonly List<PrivateArea> EnabledManagedWards = new List<PrivateArea>();

		private static readonly HashSet<int> ManagedWardIds = new HashSet<int>();

		private static readonly HashSet<int> EnabledManagedWardIds = new HashSet<int>();

		private static bool _wardCacheInitialized;

		internal static void RegisterManagedWard(PrivateArea? area)
		{
			RefreshManagedWardState(area);
		}

		internal static void RefreshManagedWardState(PrivateArea? area)
		{
			if ((Object)(object)area == (Object)null)
			{
				return;
			}
			EnsureManagedWardCacheInitialized();
			if (!IsTrackableManagedWard(area, requireEnabled: false))
			{
				UnregisterManagedWard(area);
				return;
			}
			int instanceID = ((Object)area).GetInstanceID();
			if (ManagedWardIds.Add(instanceID))
			{
				ManagedWards.Add(area);
			}
			if (area.IsEnabled())
			{
				if (EnabledManagedWardIds.Add(instanceID))
				{
					EnabledManagedWards.Add(area);
				}
			}
			else if (EnabledManagedWardIds.Remove(instanceID))
			{
				EnabledManagedWards.Remove(area);
			}
		}

		internal static void UnregisterManagedWard(PrivateArea? area)
		{
			if (!((Object)(object)area == (Object)null))
			{
				int instanceID = ((Object)area).GetInstanceID();
				if (ManagedWardIds.Remove(instanceID))
				{
					ManagedWards.Remove(area);
				}
				if (EnabledManagedWardIds.Remove(instanceID))
				{
					EnabledManagedWards.Remove(area);
				}
			}
		}

		internal static bool HasEnabledManagedWards()
		{
			return GetManagedWards(requireEnabled: true).Count > 0;
		}

		internal static IReadOnlyList<PrivateArea> GetManagedWards(bool requireEnabled)
		{
			EnsureManagedWardCacheInitialized();
			CleanupManagedWardCache(ManagedWards, ManagedWardIds, requireEnabled: false);
			CleanupManagedWardCache(EnabledManagedWards, EnabledManagedWardIds, requireEnabled: true);
			return requireEnabled ? EnabledManagedWards : ManagedWards;
		}

		internal static bool CheckAccess(Vector3 point, float radius, long playerId, bool flash = true, bool wardCheck = false)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<PrivateArea> managedWards = GetManagedWards(requireEnabled: true);
			if (managedWards.Count == 0)
			{
				return true;
			}
			bool flag = false;
			bool flag2 = false;
			List<PrivateArea> list = (flash ? new List<PrivateArea>() : null);
			foreach (PrivateArea item in managedWards)
			{
				if ((Object)(object)item == (Object)null || !item.IsInside(point, radius))
				{
					continue;
				}
				flag = true;
				if (!HasPlayerAccess(item, playerId))
				{
					flag2 = true;
					list?.Add(item);
					if (wardCheck)
					{
						break;
					}
				}
			}
			if (!flag)
			{
				return true;
			}
			bool flag3 = !flag2;
			if (!flag3 && list != null)
			{
				foreach (PrivateArea item2 in list)
				{
					item2.FlashShield(false);
				}
			}
			return flag3;
		}

		internal static bool TryBlockInteraction(Component target, Player? player, ref bool result)
		{
			if (!ShouldBlock(target, player, 0f))
			{
				return true;
			}
			ShowNoAccessMessage(player);
			result = true;
			return false;
		}

		internal static bool TryBlockAction(Component target, Player? player, ref bool result)
		{
			if (!ShouldBlock(target, player, 0f))
			{
				return true;
			}
			ShowNoAccessMessage(player);
			result = false;
			return false;
		}

		internal static bool TryBlockVoid(Component target, Player? player)
		{
			if (!ShouldBlock(target, player, 0f))
			{
				return true;
			}
			ShowNoAccessMessage(player);
			return false;
		}

		internal static bool TryBlockPlacement(Player? player, Vector3 point, float radius, ref bool result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldBlock(point, radius, player))
			{
				return true;
			}
			ShowNoAccessMessage(player);
			result = false;
			return false;
		}

		internal static bool TryBlockPlacement(Player? player, Vector3 point, float radius)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldBlock(point, radius, player))
			{
				return true;
			}
			ShowNoAccessMessage(player);
			return false;
		}

		internal static bool TryBlockItemUse(Player? player, ItemData? item, ref bool result)
		{
			if (!ShouldBlockConfiguredItemUse(player, item))
			{
				return true;
			}
			ShowBlockedItemMessage(player);
			result = false;
			return false;
		}

		internal static bool TryBlockItemUse(Player? player, ItemData? item)
		{
			if (!ShouldBlockConfiguredItemUse(player, item))
			{
				return true;
			}
			ShowBlockedItemMessage(player);
			return false;
		}

		internal static bool TryBlockItemUse(Player? player, ItemData? item, Vector3 targetPoint)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldBlockConfiguredItemUse(player, item, targetPoint))
			{
				return true;
			}
			ShowBlockedItemMessage(player);
			return false;
		}

		internal static bool TryForceUnequipBlockedItems(Player? player)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (!HasEnabledManagedWards())
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			List<ItemData> equippedItems = inventory.GetEquippedItems();
			if (equippedItems == null || equippedItems.Count == 0)
			{
				return false;
			}
			bool flag = false;
			foreach (ItemData item in equippedItems)
			{
				if (!IsConfiguredBlockedItem(item))
				{
					continue;
				}
				flag = true;
				break;
			}
			if (!flag)
			{
				return false;
			}
			if (!ShouldBlock(((Component)player).transform.position, 0f, player, flash: false))
			{
				return false;
			}
			bool flag2 = false;
			foreach (ItemData item2 in equippedItems)
			{
				if (IsConfiguredBlockedItem(item2))
				{
					((Humanoid)player).UnequipItem(item2, false);
					flag2 = true;
				}
			}
			if (flag2)
			{
				ShowBlockedItemMessage(player);
			}
			return flag2;
		}

		internal static bool TryBlockAttack(Player? player, ref bool result)
		{
			return TryBlockAttack(player, (player != null) ? ((Humanoid)player).GetCurrentWeapon() : null, ref result);
		}

		internal static bool TryBlockAttack(Player? player, ItemData? item, ref bool result)
		{
			if (!ShouldBlockConfiguredItemUse(player, item) && !ShouldBlockConfiguredItemUseAgainstHoveredTamedCreature(player, item))
			{
				return true;
			}
			if (!TryForceUnequipBlockedItems(player))
			{
				ShowBlockedItemMessage(player);
			}
			result = false;
			return false;
		}

		internal static bool ShouldBlock(Component? target, Player? player, float radius, bool flash = true)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			return ShouldBlock(target.transform.position, radius, player, flash);
		}

		internal static bool ShouldBlock(Vector3 point, float radius, Player? player, bool flash = true)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!HasEnabledManagedWards())
			{
				return false;
			}
			return !CheckAccess(point, radius, player.GetPlayerID(), flash);
		}

		internal static bool ShouldBlockPickup(GameObject? go, Player? player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			return ShouldBlock(go.transform.position, 0f, player);
		}

		internal static void ShowNoAccessMessage(Player? player)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				((Character)player).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null);
			}
		}

		internal static void ShowBlockedItemMessage(Player? player)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				((Character)player).Message((MessageType)2, WardLocalization.Localize("$stuw_msg_blocked_item", "A ward prevents using this item here."), 0, (Sprite)null);
			}
		}

		internal static void ShowWardOverlapMessage(Player? player)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				((Character)player).Message((MessageType)2, WardLocalization.Localize("$stuw_msg_overlap", "Another Ward is too close."), 0, (Sprite)null);
			}
		}

		internal static void ShowWardLimitMessage(Player? player, int limit)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				string text = ((limit >= 0) ? WardLocalization.LocalizeFormat("$stuw_msg_limit_with_max", "You can't place more Wards. ({0} max)", limit) : WardLocalization.Localize("$stuw_msg_limit", "You can't place more Wards."));
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null);
			}
		}

		internal static Player? GetPlayer(Humanoid? humanoid)
		{
			return (Player?)(object)((humanoid is Player) ? humanoid : null);
		}

		internal static Player? GetPlayer(Collider? collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return null;
			}
			return ((Component)collider).GetComponentInParent<Player>();
		}

		internal static float GetTerrainRadius(GameObject? prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return 0f;
			}
			TerrainModifier component = prefab.GetComponent<TerrainModifier>();
			if ((Object)(object)component != (Object)null)
			{
				return component.GetRadius();
			}
			TerrainOp component2 = prefab.GetComponent<TerrainOp>();
			return ((Object)(object)component2 != (Object)null) ? component2.GetRadius() : 0f;
		}

		internal static bool IsRelevantWard(PrivateArea? area)
		{
			return IsManagedWard(area, requireEnabled: true);
		}

		internal static bool IsManagedWard(PrivateArea? area, bool requireEnabled)
		{
			return IsTrackableManagedWard(area, requireEnabled);
		}

		internal static bool CanConfigureWard(PrivateArea? area, Player? player)
		{
			if ((Object)(object)area == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !IsManagedWard(area, requireEnabled: false))
			{
				return false;
			}
			Piece val = (((Object)(object)area.m_piece != (Object)null) ? area.m_piece : ((Component)area).GetComponent<Piece>());
			return ((Object)(object)val != (Object)null && val.GetCreator() == player.GetPlayerID()) || WardAdminDebugAccess.CanLocallyControlAnyWard(area, player);
		}

		internal static bool CanControlManagedWard(PrivateArea? area, long playerId)
		{
			if ((Object)(object)area == (Object)null || playerId == 0L || !IsManagedWard(area, requireEnabled: false))
			{
				return false;
			}
			Piece val = (((Object)(object)area.m_piece != (Object)null) ? area.m_piece : ((Component)area).GetComponent<Piece>());
			return ((Object)(object)val != (Object)null && val.GetCreator() == playerId) || WardAdminDebugAccess.IsPlayerAdminDebugController(playerId);
		}

		internal static bool TryBlockManagedWardPlacement(Player? player, Component? candidate, Vector3 point, ref bool result)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!IsManagedWardCandidate(candidate))
			{
				return true;
			}
			if (WardOwnership.HasReachedWardLimit(player, out var _, out var limit))
			{
				ShowWardLimitMessage(player, limit);
				result = false;
				return false;
			}
			if (!ShouldBlockManagedWardPlacement(player, candidate, point, flash: true))
			{
				return true;
			}
			ShowWardOverlapMessage(player);
			result = false;
			return false;
		}

		internal static bool TryBlockManagedWardPlacement(Player? player, Component? candidate, Vector3 point)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!IsManagedWardCandidate(candidate))
			{
				return true;
			}
			if (WardOwnership.HasReachedWardLimit(player, out var _, out var limit))
			{
				ShowWardLimitMessage(player, limit);
				return false;
			}
			if (!ShouldBlockManagedWardPlacement(player, candidate, point, flash: true))
			{
				return true;
			}
			ShowWardOverlapMessage(player);
			return false;
		}

		internal static float GetMaxNonOverlappingRadius(PrivateArea? area)
		{
			return GetMaxNonOverlappingRadius(area, WardSettings.MaxRadius);
		}

		internal static float GetMaxNonOverlappingRadius(PrivateArea? area, float fallbackRadius)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			long wardOwnerId = GetWardOwnerId(area);
			int guildId = (GuildsCompat.IsAvailable() ? GuildsCompat.GetWardGuildId(area) : 0);
			return ((Object)(object)area == (Object)null) ? fallbackRadius : GetMaxNonOverlappingRadius(((Component)area).transform.position, wardOwnerId, guildId, area, fallbackRadius);
		}

		internal static float GetMaxNonOverlappingRadius(Vector3 point, long ownerId, int guildId, PrivateArea? ignoredWard, float fallbackRadius)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			float num = fallbackRadius;
			IReadOnlyList<PrivateArea> managedWards = GetManagedWards(requireEnabled: false);
			if (managedWards.Count == 0)
			{
				return num;
			}
			foreach (PrivateArea item in managedWards)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)ignoredWard) && !SharesTrustedWardGroup(item, ownerId, guildId))
				{
					float num2 = Utils.DistanceXZ(((Component)item).transform.position, point) - WardSettings.GetRadius(item);
					if (num2 < num)
					{
						num = num2;
					}
				}
			}
			return Mathf.Clamp(num, 0f, fallbackRadius);
		}

		internal static long GetWardOwnerId(PrivateArea? area)
		{
			Piece val = (((Object)(object)area?.m_piece != (Object)null) ? area.m_piece : ((area != null) ? ((Component)area).GetComponent<Piece>() : null));
			return ((Object)(object)val != (Object)null) ? val.GetCreator() : 0;
		}

		internal static PrivateArea? FindNearestManagedWard(Vector3 point, float radius = 0f, bool requireEnabled = true, Predicate<PrivateArea>? predicate = null)
		{
			//IL_0047: 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)
			IReadOnlyList<PrivateArea> managedWards = GetManagedWards(requireEnabled);
			if (managedWards.Count == 0)
			{
				return null;
			}
			PrivateArea result = null;
			float num = float.MaxValue;
			foreach (PrivateArea item in managedWards)
			{
				if (!((Object)(object)item == (Object)null) && item.IsInside(point, radius) && (predicate == null || predicate(item)))
				{
					float num2 = Utils.DistanceXZ(((Component)item).transform.position, point);
					if (!(num2 >= num))
					{
						num = num2;
						result = item;
					}
				}
			}
			return result;
		}

		private static bool HasPlayerAccess(PrivateArea area, long playerId)
		{
			if (playerId == 0)
			{
				return area.HaveLocalAccess() || GuildsCompat.PlayerMatchesWardGuild(Player.m_localPlayer, area);
			}
			Piece val = (((Object)(object)area.m_piece != (Object)null) ? area.m_piece : ((Component)area).GetComponent<Piece>());
			if ((Object)(object)val != (Object)null && val.GetCreator() == playerId)
			{
				return true;
			}
			if (GuildsCompat.PlayerIdMatchesWardGuild(playerId, area))
			{
				return true;
			}
			List<KeyValuePair<long, string>> permittedPlayers = area.GetPermittedPlayers();
			for (int i = 0; i < permittedPlayers.Count; i++)
			{
				if (permittedPlayers[i].Key == playerId)
				{
					return true;
				}
			}
			return false;
		}

		private static bool ShouldBlockConfiguredItemUse(Player? player, ItemData? item)
		{
			return ShouldBlockConfiguredItemUse(player, item, null);
		}

		private static bool ShouldBlockConfiguredItemUse(Player? player, ItemData? item, Vector3? targetPoint)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || item == null)
			{
				return false;
			}
			if (!HasEnabledManagedWards())
			{
				return false;
			}
			if (!IsConfiguredBlockedItem(item))
			{
				return false;
			}
			if (ShouldBlock(((Component)player).transform.position, 0f, player))
			{
				return true;
			}
			return targetPoint.HasValue && ShouldBlock(targetPoint.Value, 0f, player);
		}

		private static bool ShouldBlockConfiguredItemUseAgainstHoveredTamedCreature(Player? player, ItemData? item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 targetPoint;
			return TryGetHoveredTamedCreaturePoint(player, out targetPoint) && ShouldBlockConfiguredItemUse(player, item, targetPoint);
		}

		private static bool IsConfiguredBlockedItem(ItemData? item)
		{
			if (item == null)
			{
				return false;
			}
			string prefabName = GetPrefabName(item);
			return Plugin.IsBlockedItem(prefabName);
		}

		private static bool TryGetHoveredTamedCreaturePoint(Player? player, out Vector3 targetPoint)
		{
			//IL_0002: 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_0045: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			targetPoint = default(Vector3);
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			Character hoveringCreature = player.m_hoveringCreature;
			if ((Object)(object)hoveringCreature != (Object)null && hoveringCreature.IsTamed())
			{
				targetPoint = ((Component)hoveringCreature).transform.position;
				return true;
			}
			try
			{
				Character val = null;
				GameObject val2 = null;
				player.FindHoverObject(ref val2, ref val);
				if ((Object)(object)val == (Object)null || !val.IsTamed())
				{
					return false;
				}
				targetPoint = ((Component)val).transform.position;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool ShouldBlockManagedWardPlacement(Player? player, Component? candidate, Vector3 point, bool flash)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			PrivateArea area = (((Object)(object)candidate != (Object)null) ? (candidate.GetComponent<PrivateArea>() ?? candidate.GetComponentInParent<PrivateArea>()) : null);
			if (!StuWardArea.IsManaged(area))
			{
				return false;
			}
			float defaultRadius = WardSettings.GetDefaultRadius(area);
			return OverlapsForeignManagedWard(point, defaultRadius, player.GetPlayerID(), GuildsCompat.GetPlayerGuildId(player), null, flash);
		}

		private static bool OverlapsForeignManagedWard(Vector3 point, float radius, long ownerId, int guildId, PrivateArea? ignoredWard, bool flash)
		{
			//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)
			List<PrivateArea> list = (flash ? new List<PrivateArea>() : null);
			IReadOnlyList<PrivateArea> managedWards = GetManagedWards(requireEnabled: false);
			if (managedWards.Count == 0)
			{
				return false;
			}
			bool flag = false;
			foreach (PrivateArea item in managedWards)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)ignoredWard) && !SharesTrustedWardGroup(item, ownerId, guildId) && !(Utils.DistanceXZ(((Component)item).transform.position, point) >= WardSettings.GetRadius(item) + radius))
				{
					flag = true;
					list?.Add(item);
				}
			}
			if (!flag || list == null)
			{
				return flag;
			}
			foreach (PrivateArea item2 in list)
			{
				ZNetView val = (((Object)(object)item2.m_nview != (Object)null) ? item2.m_nview : ((Component)item2).GetComponent<ZNetView>());
				if (!((Object)(object)val == (Object)null) && val.IsValid())
				{
					item2.FlashShield(false);
				}
			}
			return true;
		}

		private static bool SharesTrustedWardGroup(PrivateArea area, long ownerId, int guildId)
		{
			if (GetWardOwnerId(area) == ownerId)
			{
				return true;
			}
			return guildId != 0 && GuildsCompat.IsAvailable() && GuildsCompat.GetWardGuildId(area) == guildId;
		}

		private static bool IsManagedWardCandidate(Component? candidate)
		{
			PrivateArea area = (((Object)(object)candidate != (Object)null) ? (candidate.GetComponent<PrivateArea>() ?? candidate.GetComponentInParent<PrivateArea>()) : null);
			return StuWardArea.IsManaged(area);
		}

		private static string GetPrefabName(ItemData item)
		{
			string prefabName = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : string.Empty);
			return NormalizePrefabName(prefabName);
		}

		private static string NormalizePrefabName(string prefabName)
		{
			if (prefabName.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				prefabName = prefabName.Substring(0, prefabName.Length - "(Clone)".Length);
			}
			return prefabName;
		}

		private static void EnsureManagedWardCacheInitialized()
		{
			if (_wardCacheInitialized)
			{
				return;
			}
			_wardCacheInitialized = true;
			ManagedWards.Clear();
			EnabledManagedWards.Clear();
			ManagedWardIds.Clear();
			EnabledManagedWardIds.Clear();
			List<PrivateArea> allAreas = PrivateArea.m_allAreas;
			if (allAreas == null)
			{
				return;
			}
			for (int i = 0; i < allAreas.Count; i++)
			{
				PrivateArea val = allAreas[i];
				if (IsTrackableManagedWard(val, requireEnabled: false))
				{
					int instanceID = ((Object)val).GetInstanceID();
					ManagedWardIds.Add(instanceID);
					ManagedWards.Add(val);
					if (val.IsEnabled())
					{
						EnabledManagedWardIds.Add(instanceID);
						EnabledManagedWards.Add(val);
					}
				}
			}
		}

		private static void CleanupManagedWardCache(List<PrivateArea> areas, HashSet<int> trackedIds, bool requireEnabled)
		{
			for (int num = areas.Count - 1; num >= 0; num--)
			{
				PrivateArea val = areas[num];
				if (!IsTrackableManagedWard(val, requireEnabled))
				{
					trackedIds.Remove(((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : 0);
					areas.RemoveAt(num);
				}
			}
		}

		private static bool IsTrackableManagedWard(PrivateArea? area, bool requireEnabled)
		{
			if ((Object)(object)area == (Object)null || Player.IsPlacementGhost(((Component)area).gameObject) || !StuWardArea.IsManaged(area))
			{
				return false;
			}
			if (requireEnabled && !area.IsEnabled())
			{
				return false;
			}
			ZNetView val = (((Object)(object)area.m_nview != (Object)null) ? area.m_nview : ((Component)area).GetComponent<ZNetView>());
			return (Object)(object)val != (Object)null && val.IsValid() && val.GetZDO() != null;
		}
	}
	internal sealed class WardGuiController : MonoBehaviour
	{
		private sealed class SliderCommitHandler : MonoBehaviour, IPointerUpHandler, IEventSystemHandler
		{
			internal Action? OnCommit { get; set; }

			public void OnPointerUp(PointerEventData eventData)
			{
				OnCommit?.Invoke();
			}
		}

		[CompilerGenerated]
		private sealed class <CloseDoorAfterDelay>d__42 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Door door;

			public float delay;

			public WardGuiController <>4__this;

			private int <key>5__1;

			private ZNetView <nview>5__2;

			private int <state>5__3;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CloseDoorAfterDelay>d__42(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<nview>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Expected O, but got Unknown
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<key>5__1 = ((Object)door).GetInstanceID();
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					<>4__this._doorCloseCoroutines.Remove(<key>5__1);
					if ((Object)(object)door == (Object)null || door.m_canNotBeClosed)
					{
						return false;
					}
					<nview>5__2 = (((Object)(object)door.m_nview != (Object)null) ? door.m_nview : ((Component)door).GetComponent<ZNetView>());
					if ((Object)(object)<nview>5__2 == (Object)null || !<nview>5__2.IsValid())
					{
						return false;
					}
					if (!WardSettings.TryGetAutoCloseDoorDelay(((Component)door).transform.position, out var _))
					{
						return false;
					}
					ZDO zDO = <nview>5__2.GetZDO();
					<state>5__3 = ((zDO != null) ? zDO.GetInt(ZDOVars.s_state, 0) : 0);
					if (<state>5__3 == 0)
					{
						return false;
					}
					<nview>5__2.InvokeRPC("UseDoor", new object[1] { true });
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private readonly Dictionary<int, Coroutine> _doorCloseCoroutines = new Dictionary<int, Coroutine>();

		private readonly List<GameObject> _permittedRows = new List<GameObject>();

		private PrivateArea? _currentWard;

		private WardConfiguration _currentConfiguration;

		private GameObject? _root;

		private GameObject? _hintRoot;

		private GameObject? _panel;

		private RectTransform? _permittedContent;

		private Text? _ownerValueText;

		private Text? _guildValueText;

		private Text? _shortcutHintText;

		private Text? _areaMarkerSpeedValueText;

		private Text? _areaMarkerAlphaValueText;

		private Text? _radiusValueText;

		private Text? _delayValueText;

		private Slider? _areaMarkerSpeedSlider;

		private Slider? _areaMarkerAlphaSlider;

		private Slider? _autoCloseDelaySlider;

		private Slider? _radiusSlider;

		private Toggle? _warningSoundToggle;

		private Toggle? _warningFlashToggle;

		private Image? _radiusLimitMarker;

		private bool _visible;

		private bool _suppressUiEvents;

		private bool _radiusCommitPending;

		private bool _layoutRebuildPending;

		private float _nextPermittedRefreshTime;

		private string _lastPermittedSnapshot = string.Empty;

		internal static WardGuiController? Instance { get; private set; }

		internal bool IsVisible => _visible;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GUIManager.OnCustomGUIAvailable += BuildGui;
			BuildGui();
		}

		private void OnDestroy()
		{
			GUIManager.OnCustomGUIAvailable -= BuildGui;
			GUIManager.BlockInput(false);
			_doorCloseCoroutines.Clear();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			if (_layoutRebuildPending && !IsTextInputFocused())
			{
				_layoutRebuildPending = false;
				RebuildLayout();
			}
			if (!_visible)
			{
				SetShortcutHintVisible(visible: false);
				TryOpenHoveredWardUi();
				return;
			}
			SetShortcutHintVisible(visible: false);
			if (Input.GetKeyDown((KeyCode)27))
			{
				CloseWardUi();
			}
			else if ((Object)(object)_currentWard == (Object)null || !WardAccess.IsManagedWard(_currentWard, requireEnabled: false))
			{
				CloseWardUi();
			}
			else if (Time.unscaledTime >= _nextPermittedRefreshTime)
			{
				_nextPermittedRefreshTime = Time.unscaledTime + 0.25f;
				RefreshPermittedPlayers(force: false);
			}
		}

		internal bool TryOpenHoveredWardUi()
		{
			if (!Plugin.IsWardSettingsShortcutDown())
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			GameObject val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.m_hovering : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			PrivateArea componentInParent = val.GetComponentInParent<PrivateArea>();
			if (!WardAccess.CanConfigureWard(componentInParent, localPlayer))
			{
				return false;
			}
			OpenWardUi(componentInParent);
			return true;
		}

		internal void OpenWardUi(PrivateArea ward)
		{
			BuildGui();
			if (!((Object)(object)_root == (Object)null))
			{
				_currentWard = ward;
				_radiusCommitPending = false;
				_currentConfiguration = WardSettings.GetConfiguration(ward);
				RefreshStaticTexts();
				RefreshControls();
				RefreshPermittedPlayers(force: true);
				SetVisible(visible: true);
			}
		}

		internal void CloseWardUi()
		{
			_currentWard = null;
			_radiusCommitPending = false;
			_lastPermittedSnapshot = string.Empty;
			SetVisible(visible: false);
		}

		internal void ScheduleDoorAutoClose(Door door)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)door == (Object)null || door.m_canNotBeClosed)
			{
				return;
			}
			if (!WardSettings.TryGetAutoCloseDoorDelay(((Component)door).transform.position, out var delay))
			{
				CancelDoorAutoClose(door);
				return;
			}
			int instanceID = ((Object)door).GetInstanceID();
			if (_doorCloseCoroutines.TryGetValue(instanceID, out Coroutine value))
			{
				((MonoBehaviour)this).StopCoroutine(value);
			}
			_doorCloseCoroutines[instanceID] = ((MonoBehaviour)this).StartCoroutine(CloseDoorAfterDelay(door, delay));
		}

		internal void CancelDoorAutoClose(Door door)
		{
			if (!((Object)(object)door == (Object)null))
			{
				int instanceID = ((Object)door).GetInstanceID();
				if (_doorCloseCoroutines.TryGetValue(instanceID, out Coroutine value))
				{
					((MonoBehaviour)this).StopCoroutine(value);
					_doorCloseCoroutines.Remove(instanceID);
				}
			}
		}

		[IteratorStateMachine(typeof(<CloseDoorAfterDelay>d__42))]
		private IEnumerator CloseDoorAfterDelay(Door door, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CloseDoorAfterDelay>d__42(0)
			{
				<>4__this = this,
				door = door,
				delay = delay
			};
		}

		private void BuildGui()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00da: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Expected O, but got Unknown
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_0640: Unknown result type (might be due to invalid IL or missing references)
			//IL_064d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0694: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_0705: Unknown result type (might be due to invalid IL or missing references)
			//IL_0719: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0756: Unknown result type (might be due to invalid IL or missing references)
			//IL_075b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0762: Unknown result type (might be due to invalid IL or missing references)
			//IL_0777: Unknown result type (might be due to invalid IL or missing references)
			//IL_0779: Unknown result type (might be due to invalid IL or missing references)
			//IL_0780: Unknown result type (might be due to invalid IL or missing references)
			//IL_081c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0826: Expected O, but got Unknown
			if ((Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				return;
			}
			Localizer.ReloadCurrentLanguageIfAvailable();
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			if ((Object)(object)_hintRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_hintRoot);
			}
			_permittedRows.Clear();
			_lastPermittedSnapshot = string.Empty;
			GUIManager instance = GUIManager.Instance;
			Vector2 panelSize = WardGuiLayoutSettings.GetPanelSize();
			_root = new GameObject("STUWardGUIRoot", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			_root.transform.SetParent(GUIManager.CustomGUIFront.transform, false);
			RectTransform component = _root.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.anchoredPosition = Vector2.zero;
			Image component2 = _root.GetComponent<Image>();
			((Graphic)component2).color = new Color(0f, 0f, 0f, 0.6f);
			((Graphic)component2).raycastTarget = true;
			_panel = instance.CreateWoodpanel(_root.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), WardGuiLayoutSettings.GetPanelOffset(), panelSize.x, panelSize.y, false);
			((Object)_panel).name = "STUWardPanel";
			GameObject val = instance.CreateText(string.Empty, GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -150f), instance.AveriaSerifBold, 18, instance.ValheimBeige, true, Color.black, 460f, 84f, false);
			((Object)val).name = "STUWardShortcutHint";
			_hintRoot = val;
			_shortcutHintText = val.GetComponent<Text>();
			if ((Object)(object)_shortcutHintText != (Object)null)
			{
				_shortcutHintText.alignment = (TextAnchor)4;
			}
			SetShortcutHintVisible(visible: false);
			Vector2 permittedListSize = WardGuiLayoutSettings.GetPermittedListSize();
			Vector2 permittedListPosition = WardGuiLayoutSettings.GetPermittedListPosition();
			Vector2 registeredPlayersHeaderPosition = WardGuiLayoutSettings.GetRegisteredPlayersHeaderPosition();
			CreateLabel(WardLocalization.Localize("$stuw_ui_title", "Ward Settings"), WardGuiLayoutSettings.GetTitlePosition(), 34, 560f, 56f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimOrange);
			_ownerValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetOwnerPosition(), 22, 800f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_guildValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetGuildPosition(), 20, 800f, 32f, (TextAnchor)3, instance.AveriaSerif, instance.ValheimBeige);
			Button val2 = CreateButton(WardLocalization.Localize("$stuw_ui_close", "Close"), WardGuiLayoutSettings.GetCloseButtonPosition(), 170f, 42f);
			((UnityEvent)val2.onClick).AddListener(new UnityAction(CloseWardUi));
			CreateLabel(WardLocalization.Localize("$stuw_ui_radius", "Ward radius"), WardGuiLayoutSettings.GetRadiusLabelPosition(), 21, 240f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_radiusSlider = CreateSlider(WardGuiLayoutSettings.GetRadiusSliderPosition(), 520f, 8f, WardSettings.MaxRadius, wholeNumbers: true);
			((UnityEvent<float>)(object)_radiusSlider.onValueChanged).AddListener((UnityAction<float>)OnRadiusSliderChanged);
			_radiusLimitMarker = CreateSliderLimitMarker(_radiusSlider, new Color(0.82f, 0.22f, 0.18f, 0.95f));
			_radiusValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetRadiusValuePosition(), 21, 120f, 36f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimYellow);
			CreateLabel(WardLocalization.Localize("$stuw_ui_range_speed", "Range speed"), WardGuiLayoutSettings.GetAreaMarkerSpeedLabelPosition(), 21, 240f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_areaMarkerSpeedSlider = CreateSlider(WardGuiLayoutSettings.GetAreaMarkerSpeedSliderPosition(), 520f, 0f, 1f, wholeNumbers: false);
			((UnityEvent<float>)(object)_areaMarkerSpeedSlider.onValueChanged).AddListener((UnityAction<float>)OnAreaMarkerSpeedSliderChanged);
			_areaMarkerSpeedValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetAreaMarkerSpeedValuePosition(), 21, 120f, 36f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimYellow);
			CreateLabel(WardLocalization.Localize("$stuw_ui_range_brightness", "Range brightness"), WardGuiLayoutSettings.GetAreaMarkerAlphaLabelPosition(), 21, 240f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_areaMarkerAlphaSlider = CreateSlider(WardGuiLayoutSettings.GetAreaMarkerAlphaSliderPosition(), 520f, 0f, 1f, wholeNumbers: false);
			((UnityEvent<float>)(object)_areaMarkerAlphaSlider.onValueChanged).AddListener((UnityAction<float>)OnAreaMarkerAlphaSliderChanged);
			_areaMarkerAlphaValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetAreaMarkerAlphaValuePosition(), 21, 120f, 36f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimYellow);
			CreateLabel(WardLocalization.Localize("$stuw_ui_door_close_delay", "Door close delay"), WardGuiLayoutSettings.GetAutoCloseDelayLabelPosition(), 21, 240f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_autoCloseDelaySlider = CreateSlider(WardGuiLayoutSettings.GetAutoCloseDelaySliderPosition(), 520f, 0f, 10f, wholeNumbers: true);
			((UnityEvent<float>)(object)_autoCloseDelaySlider.onValueChanged).AddListener((UnityAction<float>)OnAutoCloseDelaySliderChanged);
			_delayValueText = CreateLabel(string.Empty, WardGuiLayoutSettings.GetAutoCloseDelayValuePosition(), 21, 120f, 36f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimYellow);
			CreateLabel(WardLocalization.Localize("$stuw_ui_warning_effects", "Warning effects"), WardGuiLayoutSettings.GetWarningEffectsLabelPosition(), 21, 240f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			CreateLabel(WardLocalization.Localize("$stuw_ui_warning_sound", "Sound"), WardGuiLayoutSettings.GetWarningSoundLabelPosition(), 21, 120f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_warningSoundToggle = CreateToggle(WardGuiLayoutSettings.GetWarningSoundTogglePosition(), GetSliderHandleHeight(_radiusSlider));
			((UnityEvent<bool>)(object)_warningSoundToggle.onValueChanged).AddListener((UnityAction<bool>)OnWarningSoundToggleChanged);
			CreateLabel(WardLocalization.Localize("$stuw_ui_warning_flash", "Flash"), WardGuiLayoutSettings.GetWarningFlashLabelPosition(), 21, 120f, 36f, (TextAnchor)3, instance.AveriaSerifBold, instance.ValheimBeige);
			_warningFlashToggle = CreateToggle(WardGuiLayoutSettings.GetWarningFlashTogglePosition(), GetSliderHandleHeight(_radiusSlider));
			((UnityEvent<bool>)(object)_warningFlashToggle.onValueChanged).AddListener((UnityAction<bool>)OnWarningFlashToggleChanged);
			CreateLabel(WardLocalization.Localize("$stuw_ui_registered_players", "Registered players"), registeredPlayersHeaderPosition, 24, permittedListSize.x, 40f, (TextAnchor)4, instance.AveriaSerifBold, instance.ValheimOrange);
			GameObject val3 = instance.CreateScrollView(_panel.transform, false, true, 20f, 6f, instance.ValheimScrollbarHandleColorBlock, new Color(0f, 0f, 0f, 0.35f), permittedListSize.x, permittedListSize.y);
			ConfigureRect(val3.GetComponent<RectTransform>(), permittedListPosition, permittedListSize.x, permittedListSize.y);
			((Object)val3).name = "STUWardPermittedPlayers";
			ref RectTransform? permittedContent = ref _permittedContent;
			Transform obj = val3.transform.Find("Scroll View/Viewport/Content");
			permittedContent = (RectTransform?)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)_permittedContent != (Object)null)
			{
				VerticalLayoutGroup component3 = ((Component)_permittedContent).GetComponent<VerticalLayoutGroup>();
				if ((Object)(object)component3 != (Object)null)
				{
					((LayoutGroup)component3).childAlignment = (TextAnchor)0;
					((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = true;
					((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = true;
					((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = false;
					((HorizontalOrVerticalLayoutGroup)component3).spacing = 6f;
					((LayoutGroup)component3).padding = new RectOffset(8, 8, 8, 8);
				}
			}
			SetVisible(_visible);
			if (_visible && (Object)(object)_currentWard != (Object)null)
			{
				RefreshStaticTexts();
				RefreshControls();
				RefreshPermittedPlayers(force: true);
			}
		}

		internal void RebuildLayout()
		{
			BuildGui();
		}

		internal void ScheduleLayoutRebuild()
		{
			_layoutRebuildPending = true;
		}

		private void SetVisible(bool visible)
		{
			_visible = visible;
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(visible);
			}
			if (visible)
			{
				SetShortcutHintVisible(visible: false);
			}
			GUIManager.BlockInput(visible);
		}

		private void SetShortcutHintVisible(bool visible)
		{
			if ((Object)(object)_hintRoot != (Object)null)
			{
				_hintRoot.SetActive(visible);
			}
		}

		private void RefreshStaticTexts()
		{
			if (!((Object)(object)_currentWard == (Object)null) && !((Object)(object)_ownerValueText == (Object)null) && !((Object)(object)_guildValueText == (Object)null))
			{
				_ownerValueText.text = WardLocalization.LocalizeFormat("$stuw_ui_owner", "Owner: {0}", _currentWard.GetCreatorName());
				string wardGuildName = GuildsCompat.GetWardGuildName(_currentWard);
				_guildValueText.text = WardLocalization.LocalizeFormat("$stuw_ui_guild", "Guild: {0}", string.IsNullOrWhiteSpace(wardGuildName) ? "-" : wardGuildName);
			}
		}

		private void RefreshControls()
		{
			if (!((Object)(object)_areaMarkerSpeedSlider == (Object)null) && !((Object)(object)_areaMarkerSpeedValueText == (Object)null) && !((Object)(object)_areaMarkerAlphaSlider == (Object)null) && !((Object)(object)_areaMarkerAlphaValueText == (Object)null) && !((Object)(object)_autoCloseDelaySlider == (Object)null) && !((Object)(object)_radiusSlider == (Object)null) && !((Object)(object)_radiusValueText == (Object)null) && !((Object)(object)_delayValueText == (Object)null) && !((Object)(object)_warningSoundToggle == (Object)null) && !((Object)(object)_warningFlashToggle == (Object)null))
			{
				float maxRadius = (((Object)(object)_currentWard != (Object)null) ? WardSettings.GetMaxNonOverlappingRadius(_currentWard) : WardSettings.MaxRadius);
				float num = Mathf.Clamp(_currentConfiguration.Radius, 8f, WardSettings.MaxRadius);
				_suppressUiEvents = true;
				_areaMarkerSpeedSlider.value = _currentConfiguration.AreaMarkerSpeedMultiplier;
				_areaMarkerAlphaSlider.value = _currentConfiguration.AreaMarkerAlpha;
				_autoCloseDelaySlider.value = _currentConfiguration.AutoCloseDelay;
				_warningSoundToggle.isOn = _currentConfiguration.WarningSoundEnabled;
				_warningFlashToggle.isOn = _currentConfiguration.WarningFlashEnabled;
				_radiusSlider.maxValue = WardSettings.MaxRadius;
				_radiusSlider.value = num;
				_areaMarkerSpeedValueText.text = $"{Mathf.RoundToInt(_currentConfiguration.AreaMarkerSpeedMultiplier * 100f)}%";
				_areaMarkerAlphaValueText.text = $"{Mathf.RoundToInt(