Decompiled source of SkaldHall v0.0.3

SkaldHall.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Text;
using ArenaGuard.Arenas;
using ArenaGuard.Challenges;
using ArenaGuard.Config;
using ArenaGuard.Domain;
using ArenaGuard.Networking;
using ArenaGuard.Persistence;
using ArenaGuard.Rules;
using ArenaGuard.Runtime;
using ArenaGuard.Sessions;
using ArenaGuard.UI;
using ArenaGuard.World;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("jg224")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Server-authoritative NPC activities and challenge arenas for Valheim.")]
[assembly: AssemblyFileVersion("0.0.3.0")]
[assembly: AssemblyInformationalVersion("0.0.3+4b928f71d565c5898a4e848cd991c0793cffd286")]
[assembly: AssemblyProduct("SkaldHall")]
[assembly: AssemblyTitle("SkaldHall")]
[assembly: AssemblyVersion("0.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ArenaGuard
{
	[BepInPlugin("jg224.arenaguard", "SkaldHall", "0.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "jg224.arenaguard";

		public const string PluginName = "SkaldHall";

		public const string PluginVersion = "0.0.3";

		public const string JotunnGuid = "com.jotunn.jotunn";

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ArenaConfig.Bind(((BaseUnityPlugin)this).Config);
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ArenaAdminCommand());
			PrefabManager.OnVanillaPrefabsAvailable += RegisterWorldPrefabs;
			ArenaServerRuntime.Initialize();
			_harmony = new Harmony("jg224.arenaguard");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			SpeedyPathsCompatibility.TryInstall(_harmony);
			Log.LogInfo((object)"SkaldHall v0.0.3 loaded. The same version is required on the server and every client.");
		}

		private void Update()
		{
			ArenaWorldObjects.HandleAdminVisualToggle();
			ArenaWorldObjects.GrantOrRemoveAdminHammer();
			ArenaServerRuntime.TickOnMainThread();
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterWorldPrefabs;
			ArenaServerRuntime.Shutdown();
			ArenaWorldObjects.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void RegisterWorldPrefabs()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterWorldPrefabs;
			ArenaWorldObjects.RegisterPrefabs();
		}

		internal static void Debug(string message)
		{
			ConfigEntry<bool> verboseLogging = ArenaConfig.VerboseLogging;
			if (verboseLogging != null && verboseLogging.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("[debug] " + message));
				}
			}
		}
	}
}
namespace ArenaGuard.World
{
	public sealed class ArenaGateDestination
	{
		public string GateId;

		public string ArenaId;

		public Vector3 Position;

		public Quaternion Rotation;

		public float ExitDistance;
	}
	public static class ArenaTeleporters
	{
		internal const string ZdoIsHub = "arenaguard.is_hub_gate";

		internal const string ZdoIsFallback = "arenaguard.is_fallback_gate";

		public static Func<Player, string, bool, bool> GateTravelRequested;

		public static Action<string, string, string, bool> GateConfigurationRequested;

		public static Func<string, ArenaGateDestination> EntranceDestinationResolver;

		public static Func<long, ArenaGateDestination> ReturnDestinationResolver;

		public static Func<PlayerArenaRoute, bool> RouteRecorder;

		public static Action<long> RouteRollback;

		public static Action<long> SuccessfulReturn;

		public static ArenaGateDestination DestinationFromGate(ArenaGateDefinition gate, float exitDistance = 2f)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (gate == null)
			{
				return null;
			}
			return new ArenaGateDestination
			{
				GateId = gate.GateId,
				ArenaId = gate.ArenaId,
				Position = ArenaWorldObjects.ToVector3(gate.Position),
				Rotation = Quaternion.Euler(0f, gate.RotationY, 0f),
				ExitDistance = exitDistance
			};
		}

		public static bool ApplyAuthorizedGateTravel(PositionData destination, float rotationY)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!CanUseVanillaPortal(localPlayer) || float.IsNaN(rotationY) || float.IsInfinity(rotationY))
			{
				return false;
			}
			return Teleport(localPlayer, new ArenaGateDestination
			{
				Position = ArenaWorldObjects.ToVector3(destination),
				Rotation = Quaternion.Euler(0f, rotationY, 0f),
				ExitDistance = 2f
			});
		}

		public static bool TryEnterGate(Player player, ArenaGateDefinition gate)
		{
			if (gate == null)
			{
				return false;
			}
			return TryEnterGate(player, gate.GateId, gate.ArenaId);
		}

		public static bool TryEnterGate(Player player, string gateId, string arenaId)
		{
			if (!CanUseVanillaPortal(player) || string.IsNullOrWhiteSpace(gateId) || string.IsNullOrWhiteSpace(arenaId))
			{
				return false;
			}
			if (GateTravelRequested != null)
			{
				return GateTravelRequested(player, gateId, arg3: false);
			}
			ArenaGateDestination arenaGateDestination = EntranceDestinationResolver?.Invoke(gateId);
			if (arenaGateDestination == null || RouteRecorder == null)
			{
				Show(player, "$arenaguard_unconfigured");
				return false;
			}
			PlayerArenaRoute arg = new PlayerArenaRoute
			{
				PlayerId = player.GetPlayerID(),
				ArenaId = arenaId,
				OriginGateId = gateId,
				EnteredUtc = DateTime.UtcNow
			};
			if (!RouteRecorder(arg))
			{
				Show(player, "Arena route could not be saved.");
				return false;
			}
			if (Teleport(player, arenaGateDestination))
			{
				return true;
			}
			RouteRollback?.Invoke(player.GetPlayerID());
			return false;
		}

		public static bool ReturnThroughHubGate(Player player)
		{
			if (!CanUseVanillaPortal(player))
			{
				return false;
			}
			if (GateTravelRequested != null)
			{
				return GateTravelRequested(player, string.Empty, arg3: true);
			}
			ArenaGateDestination arenaGateDestination = ReturnDestinationResolver?.Invoke(player.GetPlayerID());
			if (arenaGateDestination == null)
			{
				Show(player, "Your entrance gate and fallback gate are unavailable.");
				return false;
			}
			if (!Teleport(player, arenaGateDestination))
			{
				return false;
			}
			SuccessfulReturn?.Invoke(player.GetPlayerID());
			return true;
		}

		public static bool CanUseVanillaPortal(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance != (Object)null && instance.GetGlobalKey((GlobalKeys)27))
			{
				Show(player, "$msg_blocked");
				return false;
			}
			if ((Object)(object)instance != (Object)null && instance.GetGlobalKey((GlobalKeys)28))
			{
				bool num = (Object)(object)RandEventSystem.instance != (Object)null && !string.IsNullOrEmpty(RandEventSystem.instance.GetBossEvent());
				float num2 = default(float);
				bool flag = instance.GetGlobalKey((GlobalKeys)38, ref num2) && num2 > 0f;
				if (num || flag)
				{
					Show(player, "$msg_blockedbyboss");
					return false;
				}
			}
			if (!((Humanoid)player).IsTeleportable())
			{
				Show(player, "$msg_noteleport");
				return false;
			}
			return true;
		}

		public static void ApplyGateConfiguration(string objectId, string arenaId, string displayName, bool isFallback)
		{
			if (string.IsNullOrWhiteSpace(objectId))
			{
				return;
			}
			ArenaGateBehaviour[] array = Object.FindObjectsByType<ArenaGateBehaviour>((FindObjectsSortMode)0);
			foreach (ArenaGateBehaviour arenaGateBehaviour in array)
			{
				if (arenaGateBehaviour.ObjectId == objectId)
				{
					arenaGateBehaviour.ApplyOwnedConfiguration(arenaId, displayName, isFallback);
					break;
				}
			}
		}

		private static bool Teleport(Player player, ArenaGateDestination destination)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotation = destination.Rotation;
			float num = ((destination.ExitDistance > 0f) ? destination.ExitDistance : 2f);
			Vector3 val = destination.Position + rotation * Vector3.forward * num + Vector3.up;
			return ((Character)player).TeleportTo(val, rotation, true);
		}

		private static void Show(Player player, string message)
		{
			if (player != null)
			{
				((Character)player).Message((MessageType)2, message, 0, (Sprite)null);
			}
		}
	}
	public sealed class ArenaGateBehaviour : ArenaWorldObjectBehaviour, Hoverable, Interactable, TextReceiver
	{
		public bool IsHubGate;

		public float ActivationRange = 1.5f;

		public float ExitDistance = 2f;

		public Transform ProximityRoot;

		public Color UnconnectedColor = Color.black;

		public Color ConnectedColor = Color.cyan;

		public EffectFade TargetFoundEffect;

		public MeshRenderer Model;

		public EffectList ConnectedEffects;

		private bool _wasConfigured;

		private float _colorAlpha;

		private float _nextStateRefreshTime;

		private float _nextVisualRefreshTime;

		private float _lastVisualRefreshTime;

		private bool _gateColorApplied;

		private readonly MaterialPropertyBlock _modelProperties = new MaterialPropertyBlock();

		protected override void Awake()
		{
			base.Awake();
			if (base.IsOwner)
			{
				NView.GetZDO().Set("arenaguard.is_hub_gate", IsHubGate);
			}
			else if ((Object)(object)NView != (Object)null && NView.IsValid())
			{
				IsHubGate = NView.GetZDO().GetBool("arenaguard.is_hub_gate", IsHubGate);
			}
		}

		public string GetHoverName()
		{
			string text = Read("arenaguard.display_name");
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			if (!IsHubGate)
			{
				return "$arenaguard_entrance_gate";
			}
			return "$arenaguard_hub_gate";
		}

		public string GetHoverText()
		{
			string text = (IsHubGate ? "Return through gate" : "Enter arena");
			string text2 = ArenaWorldObjects.UseKeyLabel();
			string text3 = ArenaWorldObjects.Localize(GetHoverName()) + "\n[<color=yellow><b>" + text2 + "</b></color>] " + text;
			if (ArenaWorldObjects.IsLocalAdmin())
			{
				text3 = text3 + "\n[<color=yellow><b>Shift + " + text2 + "</b></color>] Rename";
			}
			return text3;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (alt && ArenaWorldObjects.IsLocalAdmin())
			{
				string arenaId = ArenaWorldObjects.ResolveArenaId(((Component)this).transform.position, base.ArenaId);
				bool isFallback = (Object)(object)NView != (Object)null && NView.IsValid() && NView.GetZDO().GetBool("arenaguard.is_fallback_gate", false);
				ArenaUi.OpenGateAdminPanel(base.ObjectId, arenaId, GetText(), IsHubGate, isFallback);
				return true;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return Activate(val);
		}

		public bool Activate(Player player)
		{
			//IL_0035: 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 || ((Character)player).IsTeleporting())
			{
				return false;
			}
			if (IsHubGate)
			{
				return ArenaTeleporters.ReturnThroughHubGate(player);
			}
			string arenaId = ArenaWorldObjects.ResolveArenaId(((Component)this).transform.position, base.ArenaId);
			return ArenaTeleporters.TryEnterGate(player, base.ObjectId, arenaId);
		}

		private void Update()
		{
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= _nextStateRefreshTime)
			{
				_nextStateRefreshTime = unscaledTime + 0.2f;
				bool flag = IsHubGate || !string.IsNullOrWhiteSpace(base.ArenaId);
				if (flag && !_wasConfigured && ConnectedEffects != null && ConnectedEffects.HasEffects())
				{
					ConnectedEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
				}
				_wasConfigured = flag;
				if ((Object)(object)TargetFoundEffect != (Object)null)
				{
					Player localPlayer = Player.m_localPlayer;
					bool flag2 = false;
					if ((Object)(object)localPlayer != (Object)null && (Object)(object)ProximityRoot != (Object)null)
					{
						Vector3 val = ((Component)localPlayer).transform.position - ProximityRoot.position;
						flag2 = ((Vector3)(ref val)).sqrMagnitude <= ActivationRange * ActivationRange && ((Humanoid)localPlayer).IsTeleportable();
					}
					TargetFoundEffect.SetActive(flag && flag2);
				}
			}
			float num = (_wasConfigured ? 1f : 0f);
			if (!(unscaledTime < _nextVisualRefreshTime) && (!_gateColorApplied || !Mathf.Approximately(_colorAlpha, num)))
			{
				_nextVisualRefreshTime = unscaledTime + 0.05f;
				float num2 = ((_lastVisualRefreshTime <= 0f) ? 0.05f : (unscaledTime - _lastVisualRefreshTime));
				_lastVisualRefreshTime = unscaledTime;
				_colorAlpha = Mathf.MoveTowards(_colorAlpha, num, num2);
				ApplyGateColor(Color.Lerp(UnconnectedColor, ConnectedColor, _colorAlpha));
			}
		}

		private void ApplyGateColor(Color color)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Model == (Object)null))
			{
				_modelProperties.Clear();
				((Renderer)Model).GetPropertyBlock(_modelProperties);
				Material sharedMaterial = ((Renderer)Model).sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_EmissionColor"))
				{
					_modelProperties.SetColor("_EmissionColor", color);
				}
				((Renderer)Model).SetPropertyBlock(_modelProperties);
				_gateColorApplied = true;
			}
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetText()
		{
			return Read("arenaguard.display_name");
		}

		public void SetText(string text)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return;
			}
			string text2 = (text ?? string.Empty).Trim();
			if (text2.Length == 0 || text2.Length > 48)
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Gate names must be 1-48 characters.", 0, (Sprite)null);
				}
				return;
			}
			string arg = ArenaWorldObjects.ResolveArenaId(((Component)this).transform.position, base.ArenaId);
			bool arg2 = (Object)(object)NView != (Object)null && NView.IsValid() && NView.GetZDO().GetBool("arenaguard.is_fallback_gate", false);
			if (ArenaTeleporters.GateConfigurationRequested != null)
			{
				ArenaTeleporters.GateConfigurationRequested(base.ObjectId, arg, text2, arg2);
			}
		}

		public void ApplyOwnedConfiguration(string arenaId, string displayName, bool isFallback)
		{
			if (base.IsOwner)
			{
				WriteOwned("arenaguard.arena_id", arenaId);
				WriteOwned("arenaguard.display_name", displayName);
				NView.GetZDO().Set("arenaguard.is_fallback_gate", isFallback);
			}
		}
	}
	public sealed class ArenaGateTrigger : MonoBehaviour
	{
		private ArenaGateBehaviour _gate;

		private void Awake()
		{
			_gate = ((Component)this).GetComponentInParent<ArenaGateBehaviour>();
		}

		private void OnTriggerEnter(Collider colliderIn)
		{
			Player val = (((Object)(object)colliderIn != (Object)null) ? ((Component)colliderIn).GetComponent<Player>() : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
			{
				if ((Object)(object)_gate == (Object)null)
				{
					_gate = ((Component)this).GetComponentInParent<ArenaGateBehaviour>();
				}
				_gate?.Activate(val);
			}
		}
	}
	public enum ArenaWorldObjectKind
	{
		Core,
		Sign,
		EntranceGate,
		HubGate,
		StagingMarker,
		CombatantStartMarker,
		EnemySpawnMarker,
		HubGateMarker
	}
	public sealed class ArenaWorldObjectPlacement
	{
		public ArenaWorldObjectKind Kind;

		public string ObjectId;

		public string ArenaId;

		public PositionData Position;

		public float RotationY;
	}
	public static class ArenaWorldObjects
	{
		public const string AdminHammerPrefabName = "ArenaGuard_AdminHammer";

		public const string PieceTableName = "ArenaGuard_PieceTable";

		public const string CorePrefabName = "ArenaGuard_Core";

		public const string ChallengeHostPrefabName = "ArenaGuard_ChallengeHost";

		public const string SignPrefabName = "ArenaGuard_Sign";

		public const string EntranceGatePrefabName = "ArenaGuard_EntranceGate";

		public const string HubGatePrefabName = "ArenaGuard_HubGate";

		public const string StagingMarkerPrefabName = "ArenaGuard_StagingMarker";

		public const string CombatantStartMarkerPrefabName = "ArenaGuard_CombatantStartMarker";

		public const string EnemySpawnMarkerPrefabName = "ArenaGuard_EnemySpawnMarker";

		public const string HubGateMarkerPrefabName = "ArenaGuard_HubGateMarker";

		private const string SignBasePrefabName = "sign";

		private const string ChallengeHostBasePrefabName = "Dverger";

		private const string ChallengeHostIconPrefabName = "TrophyDvergr";

		internal const string ZdoObjectId = "arenaguard.object_id";

		internal const string ZdoArenaId = "arenaguard.arena_id";

		internal const string ZdoDisplayName = "arenaguard.display_name";

		internal const string ZdoPlacementReported = "arenaguard.placement_reported";

		internal const string ZdoMarkerKind = "arenaguard.marker_kind";

		internal const string ZdoMarkerSlot = "arenaguard.marker_slot";

		internal const int MarkerRequestRejected = -2;

		private static bool _registered;

		private static GameObject _adminHammerPrefab;

		private static Player _lastLocalPlayer;

		private static float _nextHammerAuditTime;

		private static float _nextGrantAttemptTime;

		private static bool _adminStatusRefreshSubscribed;

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

		public static Func<bool> LocalAdminResolver;

		public static Action<ArenaWorldObjectPlacement> PlacementRequested;

		public static Action<string> CoreRemovalRequested;

		public static Action<string, PositionData> CoreActivated;

		public static Func<string, ArenaMarkerKind, PositionData, int, int> AdminMarkerRequested;

		public static Action<string, ArenaMarkerKind, PositionData, int> AdminMarkerRemovalRequested;

		public static Func<Vector3, string> ArenaAtPositionResolver;

		public static Func<string, ArenaDefinition> ArenaDefinitionResolver;

		public static string SelectedAdminArenaId { get; private set; }

		public static bool AdminSetupVisualsEnabled => ArenaConfig.ShowAdminSetupVisuals?.Value ?? true;

		public static string AdminSetupVisualShortcut
		{
			get
			{
				//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)
				if (ArenaConfig.ToggleAdminSetupVisualsShortcut != null)
				{
					return ((object)ArenaConfig.ToggleAdminSetupVisualsShortcut.Value/*cast due to .constrained prefix*/).ToString();
				}
				return "F7";
			}
		}

		public static void RegisterPrefabs()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			if (!_registered)
			{
				RequirePieceBasePrefab("guard_stone");
				RequirePieceBasePrefab("sign");
				RequirePieceBasePrefab("portal_wood");
				RequireChallengeHostSources();
				RegisterLocalization();
				PieceTableConfig val = new PieceTableConfig();
				val.UseCategories = true;
				val.UseCustomCategories = true;
				val.CustomCategories = new string[1] { "Arena" };
				val.CanRemovePieces = true;
				CustomPieceTable val2 = new CustomPieceTable("ArenaGuard_PieceTable", val);
				if (!PieceManager.Instance.AddPieceTable(val2))
				{
					throw new InvalidOperationException("ArenaGuard could not register its admin piece table.");
				}
				CustomItem val3 = new CustomItem("ArenaGuard_AdminHammer", "Hammer");
				ConfigureAdminHammer(val3, val2.PieceTable);
				if (!ItemManager.Instance.AddItem(val3))
				{
					throw new InvalidOperationException("ArenaGuard could not register its admin hammer.");
				}
				_adminHammerPrefab = val3.ItemPrefab;
				RegisterCore();
				RegisterChallengeHost();
				RegisterSign(enabled: false);
				RegisterGate("ArenaGuard_EntranceGate", "$arenaguard_entrance_gate", isHub: false);
				RegisterGate("ArenaGuard_HubGate", "$arenaguard_hub_gate", isHub: true);
				RegisterMarker("ArenaGuard_CombatantStartMarker", "$arenaguard_combat_marker", ArenaMarkerKind.CombatantStart);
				RegisterMarker("ArenaGuard_EnemySpawnMarker", "$arenaguard_enemy_marker", ArenaMarkerKind.EnemySpawn);
				TryRegisterCompatibilityMarker("ArenaGuard_StagingMarker", "$arenaguard_staging_marker", ArenaMarkerKind.Staging);
				TryRegisterCompatibilityMarker("ArenaGuard_HubGateMarker", "$arenaguard_hub_marker", ArenaMarkerKind.HubGate);
				_registered = true;
				SubscribeAdminStatusRefresh();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Registered ArenaGuard admin hammer with Arena Core, Arena Master, two gates, and admin-only Combat/Enemy beacons.");
				}
			}
		}

		public static void SelectAdminArena(string arenaId)
		{
			SelectedAdminArenaId = arenaId ?? string.Empty;
		}

		public static bool IsLocalAdmin()
		{
			if (LocalAdminResolver != null && LocalAdminResolver())
			{
				return true;
			}
			if (SynchronizationManager.Instance != null)
			{
				return SynchronizationManager.Instance.PlayerIsAdmin;
			}
			return false;
		}

		internal static bool ShouldShowAdminSetupVisuals()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				return ArenaAdminVisualPolicy.ShouldShow(IsLocalAdmin(), AdminSetupVisualsEnabled);
			}
			return false;
		}

		public static void HandleAdminVisualToggle()
		{
			//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)
			if (ArenaConfig.ToggleAdminSetupVisualsShortcut != null)
			{
				KeyboardShortcut value = ArenaConfig.ToggleAdminSetupVisualsShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					ToggleAdminSetupVisuals();
				}
			}
		}

		public static void ToggleAdminSetupVisuals()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && ArenaConfig.ShowAdminSetupVisuals != null)
			{
				if (!IsLocalAdmin())
				{
					((Character)localPlayer).Message((MessageType)2, "Arena setup visuals are waiting for server administrator synchronization.", 0, (Sprite)null);
					return;
				}
				ArenaConfig.ShowAdminSetupVisuals.Value = !ArenaConfig.ShowAdminSetupVisuals.Value;
				RefreshAdminSetupVisuals();
				((Character)localPlayer).Message((MessageType)2, ArenaConfig.ShowAdminSetupVisuals.Value ? "Arena setup visuals shown." : ("Arena setup visuals hidden. Press " + AdminSetupVisualShortcut + " to show them again."), 0, (Sprite)null);
			}
		}

		private static void RefreshAdminSetupVisuals()
		{
			ArenaCoreBehaviour[] array = Object.FindObjectsByType<ArenaCoreBehaviour>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].RefreshAdminVisibility();
			}
			ArenaMarkerBehaviour[] array2 = Object.FindObjectsByType<ArenaMarkerBehaviour>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i].RefreshAdminVisibility();
			}
		}

		private static void SubscribeAdminStatusRefresh()
		{
			if (!_adminStatusRefreshSubscribed)
			{
				SynchronizationManager.OnAdminStatusChanged += OnAdminStatusChanged;
				_adminStatusRefreshSubscribed = true;
			}
		}

		private static void OnAdminStatusChanged()
		{
			_nextHammerAuditTime = 0f;
			_nextGrantAttemptTime = 0f;
			RefreshAdminSetupVisuals();
		}

		internal static string UseKeyLabel()
		{
			ZInput instance = ZInput.instance;
			string text = ((instance != null) ? instance.GetBoundKeyString("Use", true) : null);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return "E";
		}

		internal static string Localize(string text)
		{
			if (Localization.instance != null)
			{
				return Localization.instance.Localize(text);
			}
			return text;
		}

		public static void GrantOrRemoveAdminHammer()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)_adminHammerPrefab == (Object)null)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (_lastLocalPlayer == localPlayer && unscaledTime < _nextHammerAuditTime)
			{
				return;
			}
			_lastLocalPlayer = localPlayer;
			_nextHammerAuditTime = unscaledTime + 0.5f;
			if (!IsLocalAdmin())
			{
				RemoveAdminHammer(localPlayer);
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (FindAdminHammer(inventory) == null && !(unscaledTime < _nextGrantAttemptTime))
			{
				_nextGrantAttemptTime = unscaledTime + 5f;
				if (!inventory.AddItem(_adminHammerPrefab, 1))
				{
					((Character)localPlayer).Message((MessageType)2, "$arenaguard_hammer_inventory_full", 0, (Sprite)null);
				}
			}
		}

		public static void RemoveAdminHammer(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			ItemData val;
			while ((val = FindAdminHammer(inventory)) != null)
			{
				if (((Humanoid)player).IsItemEquiped(val))
				{
					((Humanoid)player).UnequipItem(val, false);
				}
				inventory.RemoveItem(val);
			}
		}

		public static void Shutdown()
		{
			if (_adminStatusRefreshSubscribed)
			{
				SynchronizationManager.OnAdminStatusChanged -= OnAdminStatusChanged;
				_adminStatusRefreshSubscribed = false;
			}
			RemoveAdminHammer(((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer : _lastLocalPlayer);
			_lastLocalPlayer = null;
			_nextHammerAuditTime = 0f;
			_nextGrantAttemptTime = 0f;
			ChallengeHostCharacterIds.Clear();
			SelectedAdminArenaId = string.Empty;
		}

		internal static void TrackChallengeHost(Character character)
		{
			if ((Object)(object)character != (Object)null)
			{
				ChallengeHostCharacterIds.Add(((Object)character).GetInstanceID());
			}
		}

		internal static void ForgetChallengeHost(Character character)
		{
			if ((Object)(object)character != (Object)null)
			{
				ChallengeHostCharacterIds.Remove(((Object)character).GetInstanceID());
			}
		}

		internal static bool IsChallengeHost(Character character)
		{
			if ((Object)(object)character != (Object)null)
			{
				return ChallengeHostCharacterIds.Contains(((Object)character).GetInstanceID());
			}
			return false;
		}

		public static int ApplyAdminMarker(string arenaId, ArenaMarkerKind kind, Vector3 position, int slot = -1)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!IsLocalAdmin() || string.IsNullOrWhiteSpace(arenaId))
			{
				return -2;
			}
			if (AdminMarkerRequested != null)
			{
				return AdminMarkerRequested(arenaId, kind, ToPositionData(position), slot);
			}
			return -2;
		}

		internal static void RemoveAdminMarker(string arenaId, ArenaMarkerKind kind, Vector3 position, int slot)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (IsLocalAdmin() && !string.IsNullOrWhiteSpace(arenaId))
			{
				AdminMarkerRemovalRequested?.Invoke(arenaId, kind, ToPositionData(position), slot);
			}
		}

		internal static int ResolveConfiguredEnemySlot(string arenaId, Vector3 position)
		{
			//IL_0073: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			ArenaDefinition arenaDefinition = ArenaDefinitionResolver?.Invoke(arenaId);
			if (arenaDefinition?.Markers?.EnemySpawnPositions == null)
			{
				return -2;
			}
			for (int i = 0; i < arenaDefinition.Markers.EnemySpawnPositions.Count && i < 4; i++)
			{
				PositionData positionData = arenaDefinition.Markers.EnemySpawnPositions[i];
				if (positionData.X != float.MaxValue || positionData.Y != float.MaxValue || positionData.Z != float.MaxValue)
				{
					float num = positionData.X - position.x;
					float num2 = positionData.Y - position.y;
					float num3 = positionData.Z - position.z;
					if (num * num + num2 * num2 + num3 * num3 <= 0.25f)
					{
						return i;
					}
				}
			}
			return -2;
		}

		public static void OpenArenaSign(string arenaId)
		{
			if (!string.IsNullOrWhiteSpace(arenaId))
			{
				ArenaUi.OpenChallengeMenu(arenaId);
			}
		}

		public static void ApplyArenaConfiguration(string arenaId, string displayName)
		{
			ArenaCoreBehaviour[] array = Object.FindObjectsByType<ArenaCoreBehaviour>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (ArenaCoreBehaviour arenaCoreBehaviour in array)
			{
				if (string.Equals(arenaCoreBehaviour.ObjectId, arenaId, StringComparison.Ordinal) || string.Equals(arenaCoreBehaviour.ArenaId, arenaId, StringComparison.Ordinal))
				{
					arenaCoreBehaviour.ApplyOwnedDisplayName(displayName);
				}
			}
		}

		internal static string ResolveArenaId(Vector3 position, string current)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(current))
			{
				return current;
			}
			if (!string.IsNullOrWhiteSpace(SelectedAdminArenaId))
			{
				return SelectedAdminArenaId;
			}
			return ArenaAtPositionResolver?.Invoke(position) ?? string.Empty;
		}

		internal static void ReportPlacement(ArenaWorldObjectBehaviour worldObject)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (PlacementRequested == null || (Object)(object)worldObject == (Object)null || !worldObject.IsOwner)
			{
				return;
			}
			ZNetView view = worldObject.View;
			ZDO val = (((Object)(object)view != (Object)null) ? view.GetZDO() : null);
			if (val != null && !val.GetBool("arenaguard.placement_reported", false))
			{
				Vector3 worldPosition = worldObject.WorldPosition;
				string text = ((worldObject.Kind == ArenaWorldObjectKind.Core) ? worldObject.ObjectId : ResolveArenaId(worldPosition, worldObject.ArenaId));
				if (!string.IsNullOrWhiteSpace(text) && string.IsNullOrWhiteSpace(worldObject.ArenaId))
				{
					val.Set("arenaguard.arena_id", text);
				}
				PlacementRequested(new ArenaWorldObjectPlacement
				{
					Kind = worldObject.Kind,
					ObjectId = worldObject.ObjectId,
					ArenaId = text,
					Position = ToPositionData(worldPosition),
					RotationY = worldObject.WorldRotationY
				});
				val.Set("arenaguard.placement_reported", true);
			}
		}

		internal static PositionData ToPositionData(Vector3 position)
		{
			//IL_000a: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			return new PositionData
			{
				X = position.x,
				Y = position.y,
				Z = position.z
			};
		}

		internal static Vector3 ToVector3(PositionData position)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(position.X, position.Y, position.Z);
		}

		private static ItemData FindAdminHammer(Inventory inventory)
		{
			if (inventory == null)
			{
				return null;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if ((Object)(object)allItem?.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "ArenaGuard_AdminHammer")
				{
					return allItem;
				}
			}
			return null;
		}

		private static void ConfigureAdminHammer(CustomItem hammer, PieceTable table)
		{
			if (((hammer == null) ? null : hammer.ItemDrop?.m_itemData?.m_shared) == null)
			{
				throw new InvalidOperationException("The cloned vanilla hammer is missing ItemDrop shared data.");
			}
			SharedData shared = hammer.ItemDrop.m_itemData.m_shared;
			shared.m_name = "$arenaguard_admin_hammer";
			shared.m_description = "$arenaguard_admin_hammer_description";
			shared.m_buildPieces = table;
			shared.m_questItem = true;
			shared.m_teleportable = true;
			shared.m_useDurability = false;
			shared.m_canBeReparied = false;
		}

		private static PieceConfig Piece(string name, string description)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			return new PieceConfig
			{
				Name = name,
				Description = description,
				PieceTable = "ArenaGuard_PieceTable",
				Category = "Arena",
				Enabled = true,
				AllowedInDungeons = false,
				Requirements = Array.Empty<RequirementConfig>()
			};
		}

		private static void RegisterCore()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			CustomPiece val = new CustomPiece("ArenaGuard_Core", "guard_stone", Piece("$arenaguard_core", "$arenaguard_core_description"));
			RemoveComponent<PrivateArea>(val.PiecePrefab);
			RemoveComponent<EffectArea>(val.PiecePrefab);
			RemoveComponent<Collider>(val.PiecePrefab);
			CreateArenaRadiusRing(val.PiecePrefab.transform, "CombatRadiusRing", new Color(0.05f, 0.75f, 1f, 1f));
			CreateArenaRadiusRing(val.PiecePrefab.transform, "ProtectedRadiusRing", new Color(1f, 0.65f, 0f, 1f));
			SphereCollider val2 = val.PiecePrefab.AddComponent<SphereCollider>();
			val2.center = new Vector3(0f, 1f, 0f);
			val2.radius = 1.25f;
			((Collider)val2).isTrigger = true;
			ValidateCoreInteractionPrefab(expectedBehaviour: AddWorldBehaviour<ArenaCoreBehaviour>(val.PiecePrefab, ArenaWorldObjectKind.Core), prefab: val.PiecePrefab, expectedCollider: val2);
			AddPiece(val);
		}

		private static void CreateArenaRadiusRing(Transform parent, string name, Color color)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			int num = LayerMask.NameToLayer("piece_nonsolid");
			GameObject prefab = PrefabManager.Instance.GetPrefab("sign");
			Renderer val = (Renderer)(object)((prefab != null) ? ((IEnumerable<MeshRenderer>)prefab.GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)delegate(MeshRenderer candidate)
			{
				object obj;
				if (candidate == null)
				{
					obj = null;
				}
				else
				{
					Material sharedMaterial = ((Renderer)candidate).sharedMaterial;
					obj = ((sharedMaterial != null) ? sharedMaterial.shader : null);
				}
				return (Object)obj != (Object)null;
			}) : null);
			if (num < 0 || (Object)(object)((val != null) ? val.sharedMaterial : null) == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard could not create the admin radius rings.");
			}
			GameObject val2 = new GameObject(name)
			{
				layer = num
			};
			val2.transform.SetParent(parent, false);
			val2.transform.localPosition = new Vector3(0f, 0.2f, 0f);
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			LineRenderer val3 = val2.AddComponent<LineRenderer>();
			((Renderer)val3).sharedMaterial = val.sharedMaterial;
			val3.useWorldSpace = false;
			val3.loop = true;
			val3.positionCount = 96;
			val3.startWidth = 0.16f;
			val3.endWidth = 0.16f;
			val3.numCornerVertices = 2;
			val3.numCapVertices = 2;
			val3.startColor = color;
			val3.endColor = color;
			((Renderer)val3).enabled = false;
			for (int num2 = 0; num2 < val3.positionCount; num2++)
			{
				float num3 = (float)num2 * (float)Math.PI * 2f / (float)val3.positionCount;
				val3.SetPosition(num2, new Vector3(Mathf.Cos(num3), 0f, Mathf.Sin(num3)));
			}
		}

		private static void ValidateCoreInteractionPrefab(GameObject prefab, ArenaCoreBehaviour expectedBehaviour, SphereCollider expectedCollider)
		{
			if ((Object)(object)prefab.GetComponentInChildren<PrivateArea>(true) != (Object)null || (Object)(object)prefab.GetComponentInChildren<EffectArea>(true) != (Object)null)
			{
				throw new InvalidOperationException("Arena Core prefab retained inherited ward or EffectArea behavior.");
			}
			int num = 0;
			int num2 = 0;
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (val is Hoverable)
				{
					num++;
					if ((object)val != expectedBehaviour)
					{
						throw new InvalidOperationException("Arena Core prefab retained competing Hoverable component '" + ((object)val).GetType().FullName + "'.");
					}
				}
				if (val is Interactable)
				{
					num2++;
					if ((object)val != expectedBehaviour)
					{
						throw new InvalidOperationException("Arena Core prefab retained competing Interactable component '" + ((object)val).GetType().FullName + "'.");
					}
				}
			}
			Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true);
			if (num != 1 || num2 != 1 || componentsInChildren2.Length != 1 || (object)componentsInChildren2[0] != expectedCollider || !((Collider)expectedCollider).isTrigger || (Object)(object)((Component)expectedCollider).gameObject != (Object)(object)((Component)expectedBehaviour).gameObject)
			{
				throw new InvalidOperationException("Arena Core requires one root trigger collider and exactly one shared Hoverable/Interactable handler.");
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Validated Arena Core interaction prefab: one root trigger collider and ArenaCoreBehaviour is the sole Hoverable/Interactable.");
			}
		}

		private static void RegisterChallengeHost()
		{
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("ArenaGuard_ChallengeHost", "Dverger");
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard could not clone the installed Dverger rogue prefab.");
			}
			Character component = val.GetComponent<Character>();
			Humanoid component2 = val.GetComponent<Humanoid>();
			ZNetView component3 = val.GetComponent<ZNetView>();
			Rigidbody component4 = val.GetComponent<Rigidbody>();
			BaseAI component5 = val.GetComponent<BaseAI>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null || (Object)(object)component4 == (Object)null || (Object)(object)component5 == (Object)null)
			{
				throw new InvalidOperationException("The installed Dverger rogue prefab is missing its Character, Humanoid, ZNetView, Rigidbody, or AI component.");
			}
			component.m_name = "$arenaguard_challenge_host";
			component.m_aiSkipTarget = true;
			component.m_health = 1000000f;
			((Behaviour)component5).enabled = false;
			component4.isKinematic = true;
			component4.useGravity = false;
			component4.constraints = (RigidbodyConstraints)126;
			component3.m_persistent = true;
			RemoveComponent<CharacterDrop>(val);
			int num = LayerMask.NameToLayer("piece_nonsolid");
			if (num < 0)
			{
				throw new InvalidOperationException("Valheim's piece_nonsolid layer is unavailable.");
			}
			SetLayerRecursively(val, num);
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider obj in componentsInChildren)
			{
				obj.enabled = true;
				obj.isTrigger = true;
			}
			Piece obj2 = val.GetComponent<Piece>() ?? val.AddComponent<Piece>();
			GameObject prefab = PrefabManager.Instance.GetPrefab("TrophyDvergr");
			ItemDrop val2 = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			object icon;
			if (val2 == null)
			{
				icon = null;
			}
			else
			{
				ItemData itemData = val2.m_itemData;
				icon = ((itemData != null) ? itemData.GetIcon() : null);
			}
			obj2.m_icon = (Sprite)icon;
			obj2.m_groundPiece = true;
			obj2.m_groundOnly = true;
			obj2.m_clipGround = true;
			obj2.m_noInWater = true;
			GameObject val3 = new GameObject("ArenaGuard_ChallengeInteraction")
			{
				layer = num
			};
			val3.transform.SetParent(val.transform, false);
			val3.transform.localPosition = new Vector3(0f, 1f, 0f);
			SphereCollider val4 = val3.AddComponent<SphereCollider>();
			val4.radius = 1.15f;
			((Collider)val4).isTrigger = true;
			ArenaChallengeHostBehaviour host = AddWorldBehaviour<ArenaChallengeHostBehaviour>(val3, ArenaWorldObjectKind.Sign);
			val.AddComponent<ArenaChallengeHostRemoval>();
			CustomPiece val5 = new CustomPiece(val, false, Piece("$arenaguard_challenge_host", "$arenaguard_challenge_host_description"));
			ValidateChallengeHostPrefab(val, host, val4);
			AddPiece(val5);
		}

		private static void RegisterSign(bool enabled)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			CustomPiece val = new CustomPiece("ArenaGuard_Sign", "sign", Piece("$arenaguard_sign", "$arenaguard_sign_description"));
			RemoveComponent<Sign>(val.PiecePrefab);
			ValidateSignDerivedPrefab(expectedColliders: MakeSignCollidersNonSolid(val.PiecePrefab), expectedBehaviour: AddWorldBehaviour<ArenaSignBehaviour>(val.PiecePrefab, ArenaWorldObjectKind.Sign), prefab: val.PiecePrefab, displayName: "Arena Challenge Sign");
			AddPiece(val, enabled);
		}

		private static void ValidateChallengeHostPrefab(GameObject prefab, ArenaChallengeHostBehaviour host, SphereCollider interaction)
		{
			Character component = prefab.GetComponent<Character>();
			ZNetView component2 = prefab.GetComponent<ZNetView>();
			Rigidbody component3 = prefab.GetComponent<Rigidbody>();
			BaseAI component4 = prefab.GetComponent<BaseAI>();
			Piece component5 = prefab.GetComponent<Piece>();
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true);
			bool flag = componentsInChildren.Length == 0;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				flag |= (Object)(object)val == (Object)null || (Object)(object)val.sharedMaterial == (Object)null;
			}
			bool flag2 = componentsInChildren2.Length == 0;
			Collider[] array2 = componentsInChildren2;
			foreach (Collider val2 in array2)
			{
				flag2 |= (Object)(object)val2 == (Object)null || !val2.enabled || !val2.isTrigger;
			}
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.m_persistent || (Object)(object)component3 == (Object)null || !component3.isKinematic || component3.useGravity || (Object)(object)component4 == (Object)null || ((Behaviour)component4).enabled || (Object)(object)component5 == (Object)null || (Object)(object)component5.m_icon == (Object)null || (Object)(object)host == (Object)null || (Object)(object)interaction == (Object)null || !((Collider)interaction).isTrigger || ((Component)interaction).GetComponent<Interactable>() == null || flag || flag2)
			{
				throw new InvalidOperationException("Arena Master requires a visible Dverger, persistent network state, frozen AI/body, non-solid colliders, and one interaction bubble.");
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Validated stationary Arena Master Dvergr: renderers=" + componentsInChildren.Length + ", colliders=" + componentsInChildren2.Length + ", persistent=True, aiDisabled=True, nonSolid=True."));
			}
		}

		private static void RegisterGate(string prefabName, string displayName, bool isHub)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			CustomPiece val = new CustomPiece(prefabName, "portal_wood", Piece(displayName, "$arenaguard_gate_description"));
			TeleportWorld component = val.PiecePrefab.GetComponent<TeleportWorld>();
			ArenaGateBehaviour arenaGateBehaviour = AddWorldBehaviour<ArenaGateBehaviour>(val.PiecePrefab, isHub ? ArenaWorldObjectKind.HubGate : ArenaWorldObjectKind.EntranceGate);
			arenaGateBehaviour.IsHubGate = isHub;
			if ((Object)(object)component != (Object)null)
			{
				arenaGateBehaviour.ActivationRange = component.m_activationRange;
				arenaGateBehaviour.ExitDistance = component.m_exitDistance;
				arenaGateBehaviour.ProximityRoot = component.m_proximityRoot;
				arenaGateBehaviour.UnconnectedColor = component.m_colorUnconnected;
				arenaGateBehaviour.ConnectedColor = component.m_colorTargetfound;
				arenaGateBehaviour.TargetFoundEffect = component.m_target_found;
				arenaGateBehaviour.Model = component.m_model;
				arenaGateBehaviour.ConnectedEffects = component.m_connected;
			}
			ReplacePortalTriggers(val.PiecePrefab);
			RemoveComponent<TeleportWorld>(val.PiecePrefab);
			AddPiece(val);
		}

		private static void ReplacePortalTriggers(GameObject prefab)
		{
			TeleportWorldTrigger[] componentsInChildren = prefab.GetComponentsInChildren<TeleportWorldTrigger>(true);
			foreach (TeleportWorldTrigger val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).GetComponent<ArenaGateTrigger>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<ArenaGateTrigger>();
				}
				Object.DestroyImmediate((Object)(object)val);
			}
		}

		private static void RegisterMarker(string prefabName, string displayName, ArenaMarkerKind markerKind, bool enabled = true)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			CustomPiece val = new CustomPiece(prefabName, true, Piece(displayName, markerKind switch
			{
				ArenaMarkerKind.EnemySpawn => "$arenaguard_enemy_marker_description", 
				ArenaMarkerKind.CombatantStart => "$arenaguard_combat_marker_description", 
				_ => "$arenaguard_marker_description", 
			}));
			GameObject piecePrefab = val.PiecePrefab;
			if ((Object)(object)piecePrefab == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard could not create marker prefab " + prefabName + ".");
			}
			int num = LayerMask.NameToLayer("piece_nonsolid");
			if (num < 0)
			{
				throw new InvalidOperationException("Valheim's piece_nonsolid layer is unavailable.");
			}
			SetLayerRecursively(piecePrefab, num);
			Piece component = piecePrefab.GetComponent<Piece>();
			GameObject prefab = PrefabManager.Instance.GetPrefab("TrophyDvergr");
			ItemDrop val2 = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard marker prefab has no Piece component.");
			}
			object icon;
			if (val2 == null)
			{
				icon = null;
			}
			else
			{
				ItemData itemData = val2.m_itemData;
				icon = ((itemData != null) ? itemData.GetIcon() : null);
			}
			component.m_icon = (Sprite)icon;
			component.m_groundPiece = true;
			component.m_groundOnly = true;
			component.m_clipGround = true;
			component.m_noInWater = false;
			ZNetView component2 = piecePrefab.GetComponent<ZNetView>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_persistent = true;
			}
			RemoveComponent<Collider>(piecePrefab);
			CreateMarkerVisuals(piecePrefab, markerKind, num);
			SphereCollider val3 = piecePrefab.AddComponent<SphereCollider>();
			val3.center = new Vector3(0f, 1f, 0f);
			val3.radius = 0.85f;
			((Collider)val3).isTrigger = true;
			ArenaMarkerBehaviour arenaMarkerBehaviour = AddWorldBehaviour<ArenaMarkerBehaviour>(val.PiecePrefab, MarkerObjectKind(markerKind));
			arenaMarkerBehaviour.MarkerKind = markerKind;
			ValidateMarkerPrefab(piecePrefab, arenaMarkerBehaviour, val3, displayName);
			AddPiece(val, enabled);
		}

		private static void TryRegisterCompatibilityMarker(string prefabName, string displayName, ArenaMarkerKind markerKind)
		{
			try
			{
				RegisterMarker(prefabName, displayName, markerKind, enabled: false);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not register hidden compatibility marker '" + prefabName + "'. Combat Start and Enemy Spawn remain available. " + ex));
				}
			}
		}

		private static void CreateMarkerVisuals(GameObject prefab, ArenaMarkerKind markerKind, int layer)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			CreateMarkerPrimitive(prefab.transform, (PrimitiveType)2, "FloorRing", new Vector3(0f, 0.04f, 0f), new Vector3(1.35f, 0.04f, 1.35f), layer);
			CreateMarkerPrimitive(prefab.transform, (PrimitiveType)2, "BeaconPost", new Vector3(0f, 0.9f, 0f), new Vector3(0.08f, 0.9f, 0.08f), layer);
			CreateMarkerPrimitive(prefab.transform, (PrimitiveType)0, "BeaconTop", new Vector3(0f, 1.85f, 0f), new Vector3(0.32f, 0.32f, 0.32f), layer);
		}

		internal static Color MarkerColor(ArenaMarkerKind markerKind)
		{
			//IL_002a: 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_005e: 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)
			return (Color)(markerKind switch
			{
				ArenaMarkerKind.CombatantStart => new Color(0.05f, 0.75f, 1f, 1f), 
				ArenaMarkerKind.EnemySpawn => new Color(1f, 0f, 0f, 1f), 
				ArenaMarkerKind.HubGate => new Color(1f, 0.7f, 0f, 1f), 
				_ => new Color(0.2f, 1f, 0.25f, 1f), 
			});
		}

		private static void CreateMarkerPrimitive(Transform parent, PrimitiveType type, string name, Vector3 localPosition, Vector3 localScale, int layer)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			obj.layer = layer;
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = localPosition;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = localScale;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Renderer component2 = obj.GetComponent<Renderer>();
			GameObject prefab = PrefabManager.Instance.GetPrefab("sign");
			Renderer val = (Renderer)(object)((prefab != null) ? ((IEnumerable<MeshRenderer>)prefab.GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)delegate(MeshRenderer candidate)
			{
				object obj2;
				if (candidate == null)
				{
					obj2 = null;
				}
				else
				{
					Material sharedMaterial = ((Renderer)candidate).sharedMaterial;
					obj2 = ((sharedMaterial != null) ? sharedMaterial.shader : null);
				}
				return (Object)obj2 != (Object)null;
			}) : null);
			if ((Object)(object)component2 == (Object)null || (Object)(object)((val != null) ? val.sharedMaterial : null) == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard could not resolve a Valheim marker material.");
			}
			int count = Math.Max(1, component2.sharedMaterials.Length);
			component2.sharedMaterials = Enumerable.Repeat<Material>(val.sharedMaterial, count).ToArray();
		}

		private static void ValidateMarkerPrefab(GameObject prefab, ArenaMarkerBehaviour expectedBehaviour, SphereCollider expectedCollider, string displayName)
		{
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			Renderer[] componentsInChildren2 = prefab.GetComponentsInChildren<Renderer>(true);
			Piece component = prefab.GetComponent<Piece>();
			ZNetView component2 = prefab.GetComponent<ZNetView>();
			int num = prefab.GetComponentsInChildren<MonoBehaviour>(true).Count((MonoBehaviour val) => val is Hoverable);
			int num2 = prefab.GetComponentsInChildren<MonoBehaviour>(true).Count((MonoBehaviour val) => val is Interactable);
			List<string> list = new List<string>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_icon == (Object)null)
			{
				list.Add("build Piece/icon");
			}
			if ((Object)(object)component2 == (Object)null || !component2.m_persistent)
			{
				list.Add("persistent ZNetView");
			}
			if ((Object)(object)expectedBehaviour == (Object)null)
			{
				list.Add("ArenaMarkerBehaviour");
			}
			if (componentsInChildren.Length != 1 || (object)componentsInChildren.FirstOrDefault() != expectedCollider || (Object)(object)expectedCollider == (Object)null || !((Collider)expectedCollider).isTrigger)
			{
				list.Add("one trigger-only selection collider");
			}
			if (componentsInChildren2.Length != 3 || componentsInChildren2.Any((Renderer renderer) => (Object)(object)renderer == (Object)null || (Object)(object)renderer.sharedMaterial == (Object)null))
			{
				list.Add("three initialized beacon renderers");
			}
			if (num != 1 || num2 != 1)
			{
				list.Add("one Hoverable/Interactable handler");
			}
			if (list.Count != 0)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)(displayName + " marker validation warning: " + string.Join(", ", list) + ". Registration will continue."));
				}
				return;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Validated admin-only non-solid " + displayName + ": renderers=" + componentsInChildren2.Length + ", colliders=1."));
			}
		}

		private static Collider[] MakeSignCollidersNonSolid(GameObject prefab)
		{
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			if (componentsInChildren.Length == 0)
			{
				throw new InvalidOperationException("The Valheim sign source has no selection collider.");
			}
			Collider[] array = componentsInChildren;
			foreach (Collider obj in array)
			{
				obj.enabled = true;
				obj.isTrigger = true;
			}
			return componentsInChildren;
		}

		private static void ValidateSignDerivedPrefab(GameObject prefab, ArenaWorldObjectBehaviour expectedBehaviour, Collider[] expectedColliders, string displayName)
		{
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (val is Hoverable)
				{
					num++;
					if ((object)val != expectedBehaviour)
					{
						throw new InvalidOperationException(displayName + " retained competing Hoverable component '" + ((object)val).GetType().FullName + "'.");
					}
				}
				if (val is Interactable)
				{
					num2++;
					if ((object)val != expectedBehaviour)
					{
						throw new InvalidOperationException(displayName + " retained competing Interactable component '" + ((object)val).GetType().FullName + "'.");
					}
				}
			}
			Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true);
			Renderer[] componentsInChildren3 = prefab.GetComponentsInChildren<Renderer>(true);
			MeshFilter[] componentsInChildren4 = prefab.GetComponentsInChildren<MeshFilter>(true);
			bool flag = componentsInChildren2.Length == 0 || expectedColliders == null || componentsInChildren2.Length != expectedColliders.Length;
			Collider[] array = componentsInChildren2;
			foreach (Collider val2 in array)
			{
				flag |= (Object)(object)val2 == (Object)null || !val2.enabled || !val2.isTrigger;
			}
			bool flag2 = componentsInChildren3.Length == 0 || componentsInChildren4.Length == 0;
			Renderer[] array2 = componentsInChildren3;
			foreach (Renderer val3 in array2)
			{
				flag2 |= (Object)(object)val3 == (Object)null || !val3.enabled || val3.forceRenderingOff || !((Component)val3).gameObject.activeSelf || (Object)(object)val3.sharedMaterial == (Object)null;
			}
			MeshFilter[] array3 = componentsInChildren4;
			foreach (MeshFilter val4 in array3)
			{
				bool num3 = flag2;
				int num4;
				if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.sharedMesh == (Object)null))
				{
					Bounds bounds = val4.sharedMesh.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					num4 = ((((Vector3)(ref size)).sqrMagnitude <= 0.0001f) ? 1 : 0);
				}
				else
				{
					num4 = 1;
				}
				flag2 = (byte)((num3 ? 1u : 0u) | (uint)num4) != 0;
			}
			if (num != 1 || num2 != 1 || flag || flag2)
			{
				throw new InvalidOperationException(displayName + " requires visible mesh/material data, preserved trigger colliders, and one interaction handler.");
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Validated visible non-solid " + displayName + ": renderers=" + componentsInChildren3.Length + ", meshes=" + componentsInChildren4.Length + ", colliders=" + componentsInChildren2.Length + "."));
			}
		}

		private static T AddWorldBehaviour<T>(GameObject prefab, ArenaWorldObjectKind kind) where T : ArenaWorldObjectBehaviour
		{
			T obj = prefab.GetComponent<T>() ?? prefab.AddComponent<T>();
			obj.Kind = kind;
			return obj;
		}

		private static void SetLayerRecursively(GameObject root, int layer)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			root.layer = layer;
			foreach (Transform item in root.transform)
			{
				SetLayerRecursively(((Component)item).gameObject, layer);
			}
		}

		private static ArenaWorldObjectKind MarkerObjectKind(ArenaMarkerKind markerKind)
		{
			return markerKind switch
			{
				ArenaMarkerKind.Staging => ArenaWorldObjectKind.StagingMarker, 
				ArenaMarkerKind.CombatantStart => ArenaWorldObjectKind.CombatantStartMarker, 
				ArenaMarkerKind.EnemySpawn => ArenaWorldObjectKind.EnemySpawnMarker, 
				_ => ArenaWorldObjectKind.HubGateMarker, 
			};
		}

		private static void AddPiece(CustomPiece piece, bool enabled = true)
		{
			if ((Object)(object)((piece != null) ? piece.PiecePrefab : null) == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard received an empty custom piece prefab during registration.");
			}
			if ((Object)(object)piece.Piece == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard piece '" + ((Object)piece.PiecePrefab).name + "' has no Piece component.");
			}
			if ((Object)(object)piece.Piece.m_icon == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard piece '" + ((Object)piece.PiecePrefab).name + "' has no build-menu icon.");
			}
			if (string.IsNullOrWhiteSpace(piece.Piece.m_name) || string.IsNullOrWhiteSpace(piece.Piece.m_description))
			{
				throw new InvalidOperationException("ArenaGuard piece '" + ((Object)piece.PiecePrefab).name + "' has incomplete build-menu name or description metadata.");
			}
			piece.Piece.m_enabled = enabled;
			piece.Piece.m_canBeRemoved = true;
			piece.Piece.m_resources = Array.Empty<Requirement>();
			piece.Piece.m_craftingStation = null;
			piece.Piece.m_onlyInTeleportArea = false;
			piece.Piece.m_cultivatedGroundOnly = false;
			piece.Piece.m_notOnFloor = false;
			piece.Piece.m_inCeilingOnly = false;
			piece.Piece.m_noClipping = false;
			piece.Piece.m_spaceRequirement = 0f;
			piece.Piece.m_mustConnectTo = null;
			piece.Piece.m_blockingPieces?.Clear();
			if (!PieceManager.Instance.AddPiece(piece))
			{
				throw new InvalidOperationException("ArenaGuard could not register piece " + ((Object)piece.PiecePrefab).name + ".");
			}
			piece.Piece.m_enabled = enabled;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Registered ArenaGuard build piece '" + ((Object)piece.PiecePrefab).name + "' (" + piece.Piece.m_name + ")."));
			}
		}

		private static void RequirePieceBasePrefab(string prefabName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
			Piece val = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent<Piece>());
			if ((Object)(object)prefab == (Object)null || (Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard requires the installed Valheim piece prefab '" + prefabName + "', but it was not available.");
			}
			if ((Object)(object)val.m_icon == (Object)null)
			{
				throw new InvalidOperationException("Valheim piece prefab '" + prefabName + "' has no icon for ArenaGuard to inherit.");
			}
		}

		private static void RequireChallengeHostSources()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("Dverger");
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("TrophyDvergr");
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<Character>() == (Object)null || (Object)(object)prefab.GetComponent<Humanoid>() == (Object)null || (Object)(object)prefab.GetComponent<ZNetView>() == (Object)null || (Object)(object)prefab.GetComponent<Rigidbody>() == (Object)null || (Object)(object)prefab.GetComponent<BaseAI>() == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard requires the installed Valheim Dverger rogue prefab with its standard character components.");
			}
			object obj;
			if (prefab2 == null)
			{
				obj = null;
			}
			else
			{
				ItemDrop component = prefab2.GetComponent<ItemDrop>();
				if (component == null)
				{
					obj = null;
				}
				else
				{
					ItemData itemData = component.m_itemData;
					obj = ((itemData != null) ? itemData.GetIcon() : null);
				}
			}
			if ((Object)obj == (Object)null)
			{
				throw new InvalidOperationException("ArenaGuard requires the installed TrophyDvergr prefab for the Arena Master build icon.");
			}
		}

		private static void RemoveComponent<T>(GameObject prefab) where T : Component
		{
			T[] componentsInChildren = prefab.GetComponentsInChildren<T>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		private static void RegisterLocalization()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				["arenaguard_admin_hammer"] = "Arena Admin Hammer",
				["arenaguard_admin_hammer_description"] = "Admin-only tool for placing and configuring arenas.",
				["arenaguard_hammer_inventory_full"] = "Make one inventory space for the Arena Admin Hammer.",
				["arenaguard_core"] = "Arena Core",
				["arenaguard_core_description"] = "Defines an administrator-managed protected arena.",
				["arenaguard_sign"] = "Arena Challenge Sign",
				["arenaguard_sign_description"] = "Choose a challenge or view the server leaderboard.",
				["arenaguard_challenge_host"] = "Arena Master",
				["arenaguard_challenge_host_description"] = "Talk to this named Dvergr rogue to choose a challenge or view the server leaderboard.",
				["arenaguard_entrance_gate"] = "Arena Gate",
				["arenaguard_hub_gate"] = "Arena Return Gate",
				["arenaguard_gate_description"] = "A named SkaldHall portal which preserves vanilla teleport restrictions.",
				["arenaguard_staging_marker"] = "Staging Position",
				["arenaguard_combat_marker"] = "Combat Start Position",
				["arenaguard_enemy_marker"] = "Enemy Spawn Position",
				["arenaguard_hub_marker"] = "Hub Gate Position",
				["arenaguard_marker_description"] = "Place this marker with the Arena Admin Hammer.",
				["arenaguard_combat_marker_description"] = "Admin-only cyan beacon for the combatant's starting point. Place exactly one.",
				["arenaguard_enemy_marker_description"] = "Admin-only red enemy spawn beacon. Place four; they number themselves automatically.",
				["arenaguard_admin_only"] = "Only a server administrator can use this.",
				["arenaguard_admin_build_only"] = "Only an authorized arena administrator may build or demolish here.",
				["arenaguard_unconfigured"] = "This arena object has not been configured yet.",
				["arenaguard_gate_name_topic"] = "Unique gate name"
			};
			string text = "English";
			LocalizationManager.Instance.GetLocalization().AddTranslation(ref text, dictionary);
		}
	}
	public abstract class ArenaWorldObjectBehaviour : MonoBehaviour
	{
		public ArenaWorldObjectKind Kind;

		protected ZNetView NView;

		public ZNetView View => NView;

		public bool IsOwner
		{
			get
			{
				if ((Object)(object)NView != (Object)null && NView.IsValid())
				{
					return NView.IsOwner();
				}
				return false;
			}
		}

		public string ObjectId => GetOrCreateObjectId();

		public string ArenaId => Read(ZdoArenaId);

		public virtual Vector3 WorldPosition => ((Component)this).transform.position;

		public virtual float WorldRotationY => ((Component)this).transform.eulerAngles.y;

		protected static string ZdoArenaId => "arenaguard.arena_id";

		protected virtual void Awake()
		{
			NView = ((Component)this).GetComponent<ZNetView>() ?? ((Component)this).GetComponentInParent<ZNetView>();
			GetOrCreateObjectId();
		}

		protected virtual void Start()
		{
			ArenaWorldObjects.ReportPlacement(this);
		}

		protected string Read(string key)
		{
			ZDO obj = (((Object)(object)NView != (Object)null) ? NView.GetZDO() : null);
			return ((obj != null) ? obj.GetString(key, string.Empty) : null) ?? string.Empty;
		}

		protected int ReadInt(string key, int fallback)
		{
			ZDO obj = (((Object)(object)NView != (Object)null) ? NView.GetZDO() : null);
			if (obj == null)
			{
				return fallback;
			}
			return obj.GetInt(key, fallback);
		}

		protected bool ReadBool(string key, bool fallback)
		{
			ZDO obj = (((Object)(object)NView != (Object)null) ? NView.GetZDO() : null);
			if (obj == null)
			{
				return fallback;
			}
			return obj.GetBool(key, fallback);
		}

		protected void WriteOwned(string key, string value)
		{
			if (IsOwner)
			{
				NView.GetZDO().Set(key, value ?? string.Empty);
			}
		}

		protected void WriteOwned(string key, int value)
		{
			if (IsOwner)
			{
				NView.GetZDO().Set(key, value);
			}
		}

		private string GetOrCreateObjectId()
		{
			string text = Read("arenaguard.object_id");
			if (string.IsNullOrWhiteSpace(text) && IsOwner)
			{
				text = Guid.NewGuid().ToString("N").ToLowerInvariant();
				WriteOwned("arenaguard.object_id", text);
			}
			return text;
		}
	}
	public sealed class ArenaCoreBehaviour : ArenaWorldObjectBehaviour, Hoverable, Interactable, IRemoved
	{
		private static readonly Color CombatRadiusColor = new Color(0.05f, 0.75f, 1f, 1f);

		private static readonly Color ProtectedRadiusColor = new Color(1f, 0.65f, 0f, 1f);

		private Renderer[] _renderers = Array.Empty<Renderer>();

		private Projector[] _projectors = Array.Empty<Projector>();

		private Light[] _lights = Array.Empty<Light>();

		private LightFlicker[] _lightFlickers = Array.Empty<LightFlicker>();

		private LightLod[] _lightLods = Array.Empty<LightLod>();

		private AudioSource[] _audioSources = Array.Empty<AudioSource>();

		private SphereCollider _interactionCollider;

		private LineRenderer _combatRadiusRing;

		private LineRenderer _protectedRadiusRing;

		private readonly MaterialPropertyBlock _combatRadiusProperties = new MaterialPropertyBlock();

		private readonly MaterialPropertyBlock _protectedRadiusProperties = new MaterialPropertyBlock();

		private float _renderedCombatRadius = float.NaN;

		private float _renderedProtectedRadius = float.NaN;

		private bool _combatRadiusStyleApplied;

		private bool _protectedRadiusStyleApplied;

		private float _nextVisibilityRefresh;

		protected override void Awake()
		{
			base.Awake();
			_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			_projectors = ((Component)this).GetComponentsInChildren<Projector>(true);
			_lights = ((Component)this).GetComponentsInChildren<Light>(true);
			_lightFlickers = ((Component)this).GetComponentsInChildren<LightFlicker>(true);
			_lightLods = ((Component)this).GetComponentsInChildren<LightLod>(true);
			_audioSources = ((Component)this).GetComponentsInChildren<AudioSource>(true);
			_interactionCollider = ((Component)this).GetComponent<SphereCollider>();
			_combatRadiusRing = ((IEnumerable<LineRenderer>)((Component)this).GetComponentsInChildren<LineRenderer>(true)).FirstOrDefault((Func<LineRenderer, bool>)((LineRenderer candidate) => ((Object)candidate).name == "CombatRadiusRing"));
			_protectedRadiusRing = ((IEnumerable<LineRenderer>)((Component)this).GetComponentsInChildren<LineRenderer>(true)).FirstOrDefault((Func<LineRenderer, bool>)((LineRenderer candidate) => ((Object)candidate).name == "ProtectedRadiusRing"));
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				ApplyAdminVisibility();
			}
		}

		protected override void Start()
		{
			base.Start();
			ApplyAdminVisibility();
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextVisibilityRefresh))
			{
				_nextVisibilityRefresh = Time.unscaledTime + 0.5f;
				ApplyAdminVisibility();
			}
		}

		private void ApplyAdminVisibility()
		{
			bool flag = ArenaWorldObjects.ShouldShowAdminSetupVisuals();
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = flag;
				}
			}
			Projector[] projectors = _projectors;
			foreach (Projector val2 in projectors)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					((Behaviour)val2).enabled = flag;
				}
			}
			LightFlicker[] lightFlickers = _lightFlickers;
			foreach (LightFlicker val3 in lightFlickers)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					((Behaviour)val3).enabled = flag;
				}
			}
			LightLod[] lightLods = _lightLods;
			foreach (LightLod val4 in lightLods)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					((Behaviour)val4).enabled = flag;
				}
			}
			Light[] lights = _lights;
			foreach (Light val5 in lights)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					((Behaviour)val5).enabled = flag;
					if (!flag)
					{
						val5.intensity = 0f;
						val5.range = 0f;
					}
				}
			}
			AudioSource[] audioSources = _audioSources;
			foreach (AudioSource val6 in audioSources)
			{
				if ((Object)(object)val6 != (Object)null)
				{
					((Behaviour)val6).enabled = flag;
				}
			}
			if ((Object)(object)_interactionCollider != (Object)null)
			{
				((Collider)_interactionCollider).isTrigger = true;
				((Collider)_interactionCollider).enabled = flag;
			}
			ApplyRadiusRingVisibility(flag);
		}

		internal void RefreshAdminVisibility()
		{
			ApplyAdminVisibility();
		}

		private void ApplyRadiusRingVisibility(bool adminVisible)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			string text = ResolveCanonicalArenaId();
			if (string.IsNullOrWhiteSpace(text))
			{
				text = ArenaWorldObjects.ArenaAtPositionResolver?.Invoke(((Component)this).transform.position) ?? string.Empty;
			}
			ArenaDefinition arenaDefinition = (string.IsNullOrWhiteSpace(text) ? null : ArenaWorldObjects.ArenaDefinitionResolver?.Invoke(text));
			ApplyRadiusRing(_combatRadiusRing, arenaDefinition?.CombatRadius ?? 0f, CombatRadiusColor, adminVisible && arenaDefinition != null, _combatRadiusProperties, ref _renderedCombatRadius, ref _combatRadiusStyleApplied);
			ApplyRadiusRing(_protectedRadiusRing, arenaDefinition?.ProtectedRadius ?? 0f, ProtectedRadiusColor, adminVisible && arenaDefinition != null, _protectedRadiusProperties, ref _renderedProtectedRadius, ref _protectedRadiusStyleApplied);
		}

		private static void ApplyRadiusRing(LineRenderer ring, float radius, Color color, bool visible, MaterialPropertyBlock properties, ref float renderedRadius, ref bool styleApplied)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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)
			if ((Object)(object)ring == (Object)null)
			{
				return;
			}
			bool flag = !float.IsNaN(radius) && !float.IsInfinity(radius) && radius > 0f;
			((Renderer)ring).enabled = visible && flag;
			if (!((Renderer)ring).enabled)
			{
				return;
			}
			if (float.IsNaN(renderedRadius) || !Mathf.Approximately(renderedRadius, radius))
			{
				for (int i = 0; i < ring.positionCount; i++)
				{
					float num = (float)i * (float)Math.PI * 2f / (float)ring.positionCount;
					ring.SetPosition(i, new Vector3(Mathf.Cos(num) * radius, 0f, Mathf.Sin(num) * radius));
				}
				renderedRadius = radius;
			}
			if (!styleApplied)
			{
				ring.startColor = color;
				ring.endColor = color;
				((Renderer)ring).GetPropertyBlock(properties);
				Material sharedMaterial = ((Renderer)ring).sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_MainTex"))
				{
					properties.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
				}
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_BaseMap"))
				{
					properties.SetTexture("_BaseMap", (Texture)(object)Texture2D.whiteTexture);
				}
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_Color"))
				{
					properties.SetColor("_Color", color);
				}
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_BaseColor"))
				{
					properties.SetColor("_BaseColor", color);
				}
				if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_EmissionColor"))
				{
					properties.SetColor("_EmissionColor", color * 1.25f);
				}
				((Renderer)ring).SetPropertyBlock(properties);
				styleApplied = true;
			}
		}

		public string GetHoverName()
		{
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return string.Empty;
			}
			string text = Read("arenaguard.display_name");
			return ArenaWorldObjects.Localize(string.IsNullOrWhiteSpace(text) ? "$arenaguard_core" : text);
		}

		public string GetHoverText()
		{
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return string.Empty;
			}
			return GetHoverName() + "\n[<color=yellow><b>" + ArenaWorldObjects.UseKeyLabel() + "</b></color>] Configure arena";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				((Character)user).Message((MessageType)2, "$arenaguard_admin_only", 0, (Sprite)null);
				return true;
			}
			string text = ResolveCanonicalArenaId();
			if (string.IsNullOrWhiteSpace(text))
			{
				text = ArenaWorldObjects.ArenaAtPositionResolver?.Invoke(((Component)this).transform.position) ?? string.Empty;
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Could not open Arena Core administration because the Core has no arena ID yet.");
				}
				((Character)user).Message((MessageType)2, "This Arena Core is still initializing. Try again in a moment.", 0, (Sprite)null);
				return true;
			}
			ArenaWorldObjects.CoreActivated?.Invoke(text, ArenaWorldObjects.ToPositionData(((Component)this).transform.position));
			ArenaWorldObjects.SelectAdminArena(text);
			ArenaUi.OpenAdminPanel(text, ArenaWorldObjects.ArenaDefinitionResolver?.Invoke(text));
			return true;
		}

		public void ApplyOwnedDisplayName(string displayName)
		{
			WriteOwned("arenaguard.display_name", displayName);
		}

		public void OnRemoved()
		{
			if (ArenaWorldObjects.IsLocalAdmin())
			{
				string text = ResolveCanonicalArenaId();
				if (!string.IsNullOrWhiteSpace(text))
				{
					ArenaWorldObjects.CoreRemovalRequested?.Invoke(text);
				}
			}
		}

		private string ResolveCanonicalArenaId()
		{
			string objectId = base.ObjectId;
			if (!string.IsNullOrWhiteSpace(objectId) && ArenaWorldObjects.ArenaDefinitionResolver?.Invoke(objectId) != null)
			{
				return objectId;
			}
			if (!string.IsNullOrWhiteSpace(base.ArenaId))
			{
				return base.ArenaId;
			}
			return objectId;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public sealed class ArenaSignBehaviour : ArenaWorldObjectBehaviour, Hoverable, Interactable
	{
		protected override void Start()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			base.Start();
			if (base.IsOwner && ArenaWorldObjects.IsLocalAdmin())
			{
				ArenaWorldObjects.ApplyAdminMarker(ArenaWorldObjects.ResolveArenaId(((Component)this).transform.position, base.ArenaId), ArenaMarkerKind.Staging, ((Component)this).transform.position);
			}
		}

		public string GetHoverName()
		{
			return ArenaWorldObjects.Localize("$arenaguard_sign");
		}

		public string GetHoverText()
		{
			return GetHoverName() + "\n[<color=yellow><b>" + ArenaWorldObjects.UseKeyLabel() + "</b></color>] Choose challenge";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			string text = ArenaWorldObjects.ResolveArenaId(((Component)this).transform.position, base.ArenaId);
			if (string.IsNullOrWhiteSpace(text))
			{
				((Character)user).Message((MessageType)2, "$arenaguard_unconfigured", 0, (Sprite)null);
				return true;
			}
			ArenaWorldObjects.OpenArenaSign(text);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public sealed class ArenaChallengeHostBehaviour : ArenaWorldObjectBehaviour, Hoverable, Interactable
	{
		private Character _character;

		public override Vector3 WorldPosition
		{
			get
			{
				//IL_0025: 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)
				if (!((Object)(object)NView != (Object)null))
				{
					return ((Component)this).transform.position;
				}
				return ((Component)NView).transform.position;
			}
		}

		public override float WorldRotationY
		{
			get
			{
				//IL_002a: 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)
				if (!((Object)(object)NView != (Object)null))
				{
					return ((Component)this).transform.eulerAngles.y;
				}
				return ((Component)NView).transform.eulerAngles.y;
			}
		}

		protected override void Awake()
		{
			base.Awake();
			_character = ((Component)this).GetComponent<Character>() ?? ((Component)this).GetComponentInParent<Character>();
			ArenaWorldObjects.TrackChallengeHost(_character);
		}

		private void OnDestroy()
		{
			ArenaWorldObjects.ForgetChallengeHost(_character);
		}

		protected override void Start()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			base.Start();
			Character character = _character;
			if ((Object)(object)character != (Object)null)
			{
				character.m_name = "$arenaguard_challenge_host";
				character.m_aiSkipTarget = true;
			}
			Humanoid componentInParent = ((Component)this).GetComponentInParent<Humanoid>();
			if (base.IsOwner && (Object)(object)componentInParent != (Object)null)
			{
				componentInParent.EquipBestWeapon((Character)null, (StaticTarget)null, (Character)null, (Character)null);
			}
			if (base.IsOwner && ArenaWorldObjects.IsLocalAdmin())
			{
				ArenaWorldObjects.ApplyAdminMarker(ArenaWorldObjects.ResolveArenaId(WorldPosition, base.ArenaId), ArenaMarkerKind.Staging, WorldPosition);
			}
		}

		public string GetHoverName()
		{
			return ArenaWorldObjects.Localize("$arenaguard_challenge_host");
		}

		public string GetHoverText()
		{
			return GetHoverName() + "\n[<color=yellow><b>" + ArenaWorldObjects.UseKeyLabel() + "</b></color>] Choose challenge";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			string text = ArenaWorldObjects.ResolveArenaId(WorldPosition, base.ArenaId);
			if (string.IsNullOrWhiteSpace(text))
			{
				((Character)user).Message((MessageType)2, "$arenaguard_unconfigured", 0, (Sprite)null);
				return true;
			}
			ArenaWorldObjects.OpenArenaSign(text);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public sealed class ArenaChallengeHostRemoval : MonoBehaviour, IRemoved
	{
		public void OnRemoved()
		{
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return;
			}
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.ClaimOwnership();
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					instance.Destroy(((Component)this).gameObject);
				}
			}
		}
	}
	public sealed class ArenaMarkerBehaviour : ArenaWorldObjectBehaviour, Hoverable, Interactable, IRemoved
	{
		public ArenaMarkerKind MarkerKind;

		private Renderer[] _renderers = Array.Empty<Renderer>();

		private SphereCollider _selectionCollider;

		private readonly MaterialPropertyBlock _appearanceProperties = new MaterialPropertyBlock();

		private bool _appearanceApplied;

		private float _nextVisibilityRefresh;

		public int MarkerSlot => ReadInt("arenaguard.marker_slot", -2);

		protected override void Awake()
		{
			base.Awake();
			_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			_selectionCollider = ((Component)this).GetComponent<SphereCollider>();
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				ApplyAdminVisibility();
			}
		}

		protected override void Start()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ReadBool("arenaguard.placement_reported", fallback: false);
			base.Start();
			ApplyAdminVisibility();
			if (!base.IsOwner || !ArenaWorldObjects.IsLocalAdmin())
			{
				return;
			}
			string arenaId = ArenaWorldObjects.ResolveArenaId(WorldPosition, base.ArenaId);
			int slot = ((MarkerKind == ArenaMarkerKind.EnemySpawn) ? ResolveEnemySlot(arenaId) : (-1));
			int num = ArenaWorldObjects.ApplyAdminMarker(arenaId, MarkerKind, WorldPosition, slot);
			if (num != -2)
			{
				WriteOwned("arenaguard.marker_kind", (int)MarkerKind);
				WriteOwned("arenaguard.marker_slot", num);
			}
			else if (!flag && (Object)(object)NView != (Object)null && NView.IsValid())
			{
				NView.ClaimOwnership();
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					instance.Destroy(((Component)NView).gameObject);
				}
			}
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextVisibilityRefresh))
			{
				_nextVisibilityRefresh = Time.unscaledTime + 0.5f;
				ApplyAdminVisibility();
			}
		}

		private int ResolveEnemySlot(string arenaId)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			int markerSlot = MarkerSlot;
			if (markerSlot >= 0 && markerSlot < 4)
			{
				return markerSlot;
			}
			int num = ArenaWorldObjects.ResolveConfiguredEnemySlot(arenaId, WorldPosition);
			if (num >= 0)
			{
				return num;
			}
			HashSet<int> hashSet = new HashSet<int>();
			ArenaMarkerBehaviour[] array = Object.FindObjectsByType<ArenaMarkerBehaviour>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (ArenaMarkerBehaviour arenaMarkerBehaviour in array)
			{
				if (!((Object)(object)arenaMarkerBehaviour == (Object)null) && arenaMarkerBehaviour != this && arenaMarkerBehaviour.MarkerKind == ArenaMarkerKind.EnemySpawn && string.Equals(ArenaWorldObjects.ResolveArenaId(arenaMarkerBehaviour.WorldPosition, arenaMarkerBehaviour.ArenaId), arenaId, StringComparison.Ordinal))
				{
					int markerSlot2 = arenaMarkerBehaviour.MarkerSlot;
					if (markerSlot2 >= 0 && markerSlot2 < 4)
					{
						hashSet.Add(markerSlot2);
					}
				}
			}
			for (int j = 0; j < 4; j++)
			{
				if (!hashSet.Contains(j))
				{
					return j;
				}
			}
			return -2;
		}

		private void ApplyAdminVisibility()
		{
			//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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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)
			bool enabled = ArenaWorldObjects.ShouldShowAdminSetupVisuals();
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = enabled;
				}
			}
			if (!_appearanceApplied)
			{
				Color val2 = ArenaWorldObjects.MarkerColor(MarkerKind);
				renderers = _renderers;
				foreach (Renderer val3 in renderers)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						Material sharedMaterial = val3.sharedMaterial;
						_appearanceProperties.Clear();
						val3.GetPropertyBlock(_appearanceProperties);
						if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_MainTex"))
						{
							_appearanceProperties.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
						}
						if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_BaseMap"))
						{
							_appearanceProperties.SetTexture("_BaseMap", (Texture)(object)Texture2D.whiteTexture);
						}
						if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_Color"))
						{
							_appearanceProperties.SetColor("_Color", val2);
						}
						if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_BaseColor"))
						{
							_appearanceProperties.SetColor("_BaseColor", val2);
						}
						if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_EmissionColor"))
						{
							_appearanceProperties.SetColor("_EmissionColor", val2 * 1.4f);
						}
						val3.SetPropertyBlock(_appearanceProperties);
					}
				}
				_appearanceApplied = true;
			}
			if ((Object)(object)_selectionCollider != (Object)null)
			{
				((Collider)_selectionCollider).isTrigger = true;
				((Collider)_selectionCollider).enabled = enabled;
			}
		}

		internal void RefreshAdminVisibility()
		{
			ApplyAdminVisibility();
		}

		public string GetHoverName()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return string.Empty;
			}
			int num = MarkerSlot;
			if (MarkerKind == ArenaMarkerKind.EnemySpawn && (num < 0 || num > 3))
			{
				num = ArenaWorldObjects.ResolveConfiguredEnemySlot(ArenaWorldObjects.ResolveArenaId(WorldPosition, base.ArenaId), WorldPosition);
			}
			if (MarkerKind != ArenaMarkerKind.EnemySpawn || num < 0)
			{
				if (MarkerKind != ArenaMarkerKind.CombatantStart)
				{
					return MarkerKind.ToString() + " Position";
				}
				return "Combat Start";
			}
			return "Enemy Spawn " + (num + 1);
		}

		public string GetHoverText()
		{
			if (!ArenaWorldObjects.IsLocalAdmin())
			{
				return string.Empty;
			}
			return GetHoverName() + "\nRemove with the Arena Admin Hammer";
		}

		public void OnRemoved()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (ArenaWorldObjects.IsLocalAdmin())
			{
				string arenaId = ArenaWorldObjects.ResolveArenaId(WorldPosition, base.ArenaId);
				int num = ((MarkerKind == ArenaMarkerKind.EnemySpawn) ? MarkerSlot : (-1));
				if (MarkerKind == ArenaMarkerKind.EnemySpawn && (num < 0 || num > 3))
				{
					num = ArenaWorldObjects.ResolveConfiguredEnemySlot(arenaId, WorldPosition);
				}
				if (MarkerKind != ArenaMarkerKind.EnemySpawn || (num >= 0 && num < 4))
				{
					ArenaWorldObjects.RemoveAdminMarker(arenaId, MarkerKind, WorldPosition, num);
				}
			}
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
}
namespace ArenaGuard.UI
{
	public enum ArenaUiAdminMutationKind
	{
		SaveDefinition,
		EnableArena,
		DisableArena,
		SetTerrainPermission,
		SetBuildingPermission,
		SetPickupPermission
	}
	public enum ArenaAdminPermissionKind
	{
		Terrain,
		Building,
		DroppedItemPickup
	}
	public sealed class ArenaUiAdminMutation
	{
		public string ArenaId;

		public ArenaUiAdminMutationKind Kind;

		public string DisplayName;

		public float CombatRadius;

		public float ProtectedRadius;

		public bool Enabled;
	}
	public static class ArenaUi
	{
		private sealed class ChallengeMenuState
		{
			internal string ArenaId;

			internal ChallengeMode Mode;

			internal ProgressionCapMode CapMode;

			internal BiomeTier SelectedBiome;

			internal CreatureDefinition SelectedCreature;

			internal StarLevel Stars;

			internal int Quantity;

			internal Button[] ModeButtons;

			internal Button[] CapButtons;

			internal Button BiomeButton;

			internal Button[] StarButtons;

			internal Button ChangeCreatureButton;

			internal Button DecreaseQuantityButton;

			internal Button IncreaseQuantityButton;

			internal Image CreatureIcon;

			internal Image SecondaryCreatureIcon;

			internal Text CreatureSummary;

			internal Text ScopeSummary;

			internal Text StarsLabel;

			internal Text QuantityLabel;

			internal Text QuantityText;

			internal Text EncounterSummary;
		}

		private sealed class FoodPreparationState
		{
			internal string ArenaId;

			internal List<ArenaFoodDefinition> Foods;

			internal List<string> SelectedPrefabNames;

			internal DateTime DeadlineUtc;

			internal float[] ScrollPositions;

			internal ScrollRect[] ScrollRects;

			internal Text DeadlineLabel;
		}

		private static GameObject _modalRoot;

		private static GameObject _creaturePickerRoot;

		private static GameObject _biomePickerRoot;

		private static GameObject _hudRoot;

		private static GameObject _queueRoot;

		private static Text _hudText;

		private static Text _queueText;

		private static Button _forfeitButton;

		private static Button _setupVisibilityButton;

		private static Button _terrainPermissionButton;

		private static Button _buildingPermissionButton;

		private static Button _pickupPermissionButton;

		private static bool _inputBlocked;

		private static GameObject _driverHost;

		private static string _activeArenaId = string.Empty;

		private static string _hudArenaId = string.Empty;

		private static string _queueArenaId = string.Empty;

		private static ArenaClientSnapshot _hudSnapshot;

		private static long _hudElapsedBaseMilliseconds;

		private static float _hudElapsedBaseTime;

		private static float _nextHudTimerRefreshTime;

		private static DateTime _queueDeadlineUtc;

		private static List<CreatureDefinition> _creatures = new List<CreatureDefinition>();

		private static