Decompiled source of SkaldHall v0.5.3

SkaldHall.dll

Decompiled a month 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 JG224.ModCore.API;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
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.5.3.0")]
[assembly: AssemblyInformationalVersion("0.5.3+a70acd681700d56f2de0e31119ad45032219d3bd")]
[assembly: AssemblyProduct("SkaldHall")]
[assembly: AssemblyTitle("SkaldHall")]
[assembly: AssemblyVersion("0.5.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.skaldhall", "SkaldHall", "0.5.3")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	[BepInDependency("com.jotunn.jotunn", "2.30.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "jg224.skaldhall";

		public const string PluginName = "SkaldHall";

		public const string PluginVersion = "0.5.3";

		public const string ModCoreGuid = "com.jg224.modcore";

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

		public const int ProtocolVersion = 12;

		public static readonly ModuleId ModuleId = new ModuleId("skaldhall");

		private Harmony _harmony;

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		private bool _shutDown;

		private IDisposable _adminVisualInput;

		internal static ManualLogSource Log { get; private set; }

		internal static ICoreServices Core { get; private set; }

		internal static bool IsActive { get; private set; }

		private void Awake()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Expected O, but got Unknown
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			IsActive = false;
			_shutDown = false;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before SkaldHall.");
				}
				Core = ModCoreApi.Services;
				SemanticVersion val = default(SemanticVersion);
				if (!SemanticVersion.TryParse("0.5.3", ref val))
				{
					throw new InvalidOperationException("SkaldHall has invalid release version metadata.");
				}
				_registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.skaldhall", "SkaldHall", val, 12, (ModuleSide)3, (ModuleRequirement)4, 0uL, 1, 1)));
				_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)6, "jg224.skaldhall.", 1, Array.Empty<string>()));
				_registrations.Add(RoutedRpcIngress.Register(ModuleId, new string[16]
				{
					"jg224.skaldhall.RequestChallenge", "jg224.skaldhall.AcceptQueueCall", "jg224.skaldhall.RequestForfeit", "jg224.skaldhall.ReportLethalDamage", "jg224.skaldhall.CombatStartArrived", "jg224.skaldhall.RequestAdminMutation", "jg224.skaldhall.ArenaSnapshot", "jg224.skaldhall.ArenaRemoved", "jg224.skaldhall.RequestLeaderboard", "jg224.skaldhall.Leaderboard",
					"jg224.skaldhall.ActionResult", "jg224.skaldhall.SubmitResourceSnapshot", "jg224.skaldhall.RestoreResources", "jg224.skaldhall.AcknowledgeResourceRestore", "jg224.skaldhall.MovePlayer", "jg224.skaldhall.ApplyPoisonResistance"
				}));
				_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)4, "ArenaGuard", 4, Array.Empty<string>()));
				_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)1, "jg224.skaldhall.", 1, Array.Empty<string>()));
				_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)8, "skaldhall.", 1, Array.Empty<string>()));
				ArenaConfig.Bind(((BaseUnityPlugin)this).Config);
				RefreshAdminVisualInput(this, EventArgs.Empty);
				ArenaConfig.ToggleAdminSetupVisualsShortcut.SettingChanged += RefreshAdminVisualInput;
				CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ArenaAdminCommand());
				PrefabManager.OnVanillaPrefabsAvailable += RegisterWorldPrefabs;
				ArenaServerRuntime.Initialize();
				_harmony = new Harmony("jg224.skaldhall");
				_harmony.PatchAll(typeof(Plugin).Assembly);
				SpeedyPathsCompatibility.TryInstall(_harmony);
				IsActive = true;
				Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Required server-authoritative arena runtime and protocol ready.");
				Log.LogInfo((object)"SkaldHall v0.5.3 loaded. The same version is required on the server and every client.");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("SkaldHall failed to initialize safely: " + ex));
				if (Core != null)
				{
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

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

		private void OnDestroy()
		{
			Shutdown();
		}

		private unsafe void RefreshAdminVisualInput(object sender, EventArgs args)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			if (_shutDown)
			{
				return;
			}
			_adminVisualInput?.Dispose();
			_adminVisualInput = null;
			KeyboardShortcut value = ArenaConfig.ToggleAdminSetupVisualsShortcut.Value;
			string text = ((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).ToString();
			if (Core != null)
			{
				value = ArenaConfig.ToggleAdminSetupVisualsShortcut.Value;
				if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && !string.IsNullOrWhiteSpace(text))
				{
					_adminVisualInput = Core.Input.Register(new InputActionDescriptor(ModuleId, "toggle-setup-visuals", text, "gameplay:arena-admin-hammer-equipped", 0));
				}
			}
		}

		private void Shutdown()
		{
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (_shutDown)
			{
				return;
			}
			_shutDown = true;
			IsActive = false;
			if (ArenaConfig.ToggleAdminSetupVisualsShortcut != null)
			{
				ArenaConfig.ToggleAdminSetupVisualsShortcut.SettingChanged -= RefreshAdminVisualInput;
			}
			_adminVisualInput?.Dispose();
			_adminVisualInput = null;
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterWorldPrefabs;
			ArenaServerRuntime.Shutdown();
			ArenaWorldObjects.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			for (int num = _registrations.Count - 1; num >= 0; num--)
			{
				try
				{
					_registrations[num].Dispose();
				}
				catch (Exception ex)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)("Registration cleanup failed: " + ex.Message));
					}
				}
			}
			_registrations.Clear();
			if (Core != null)
			{
				Core.Metrics.RemoveOwner(ModuleId);
			}
			Core = null;
		}

		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
{
	[HarmonyPatch(typeof(Player), "SetSelectedPiece", new Type[] { typeof(Vector2Int) })]
	internal static class ArenaCorePlacementPreviewPatch
	{
		private static readonly MethodInfo SetupPlacementGhost = AccessTools.Method(typeof(Player), "SetupPlacementGhost", (Type[])null, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(Player __instance, GameObject ___m_placementGhost)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)___m_placementGhost != (Object)null || !((Character)__instance).InPlaceMode())
			{
				return;
			}
			Piece selectedPiece = __instance.GetSelectedPiece();
			if ((Object)(object)selectedPiece == (Object)null || (Object)(object)((Component)selectedPiece).gameObject == (Object)null || !((Object)((Component)selectedPiece).gameObject).name.StartsWith("ArenaGuard_Core", StringComparison.Ordinal))
			{
				return;
			}
			if (SetupPlacementGhost == null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)"Valheim's SetupPlacementGhost method is unavailable; the Arena Core preview cannot be repaired.");
				}
			}
			else
			{
				SetupPlacementGhost.Invoke(__instance, null);
			}
		}
	}
	public sealed class ArenaLeaderboardBoardBehaviour : ArenaWorldObjectBehaviour, Hoverable
	{
		private sealed class BoardSection
		{
			internal ArenaLeaderboardCategory Category;

			internal TextMesh Heading;

			internal TextMesh BiomeTitle;

			internal TextMesh BiomeEntries;

			internal TextMesh StarTitle;

			internal TextMesh StarEntries;
		}

		private static readonly HashSet<ArenaLeaderboardBoardBehaviour> Instances = new HashSet<ArenaLeaderboardBoardBehaviour>();

		private static readonly Dictionary<string, List<LeaderboardEntry>> CachedEntries = new Dictionary<string, List<LeaderboardEntry>>(StringComparer.Ordinal);

		private static readonly HashSet<string> PendingRequests = new HashSet<string>(StringComparer.Ordinal);

		private static float _nextGlobalRequestRetryTime;

		private readonly MaterialPropertyBlock _glowProperties = new MaterialPropertyBlock();

		private readonly List<BoardSection> _sections = new List<BoardSection>();

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

		private TextMesh _headerFront;

		private TextMesh _taglineFront;

		private float _nextRefreshTime;

		private float _nextDataRequestTime;

		private float _glowUntil;

		private bool _glowCleared = true;

		private static int _textOcclusionMask;

		protected override void Awake()
		{
			base.Awake();
			_woodRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		}

		protected override void Start()
		{
			Instances.Add(this);
			EnsureTextMeshes();
			RenderBoard();
			UpdateFrontTextVisibility();
			RequestMissingCategories();
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
		}

		private void Update()
		{
			if (!_glowCleared)
			{
				UpdateGlow();
			}
			if (!(Time.unscaledTime < _nextRefreshTime))
			{
				_nextRefreshTime = Time.unscaledTime + 0.5f;
				if ((Object)(object)_headerFront == (Object)null && !GUIManager.IsHeadless())
				{
					EnsureTextMeshes();
					RenderBoard();
				}
				UpdateFrontTextVisibility();
				if (Time.unscaledTime >= _nextDataRequestTime && !HasCompleteBoardCache())
				{
					RequestMissingCategories();
				}
			}
		}

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

		public string GetHoverText()
		{
			return GetHoverName();
		}

		internal static void ReceiveLeaderboard(LeaderboardKey key, IEnumerable<LeaderboardEntry> entries)
		{
			if (key == null || (key.Mode != ChallengeMode.BiomeLadder && key.Mode != ChallengeMode.StarLadder))
			{
				return;
			}
			string text = CacheKey(key);
			List<LeaderboardEntry> list = ArenaLeaderboardBoardPolicy.CompletedTopFive(entries);
			List<LeaderboardEntry> value;
			bool flag = CachedEntries.TryGetValue(text, out value) && !SameResults(value, list);
			CachedEntries[text] = list;
			PendingRequests.Remove(text);
			ArenaLeaderboardBoardBehaviour[] array = Instances.ToArray();
			foreach (ArenaLeaderboardBoardBehaviour arenaLeaderboardBoardBehaviour in array)
			{
				if (!((Object)(object)arenaLeaderboardBoardBehaviour == (Object)null))
				{
					arenaLeaderboardBoardBehaviour.RenderBoard();
					if (flag)
					{
						arenaLeaderboardBoardBehaviour.BeginGlow();
					}
				}
			}
		}

		internal static void ResetClientState()
		{
			CachedEntries.Clear();
			PendingRequests.Clear();
			_nextGlobalRequestRetryTime = 0f;
			Instances.Clear();
		}

		private void RequestMissingCategories()
		{
			_nextDataRequestTime = Time.unscaledTime + 5f;
			Action<LeaderboardKey> leaderboardRequested = ArenaWorldObjects.LeaderboardRequested;
			if (leaderboardRequested != null && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (Time.unscaledTime >= _nextGlobalRequestRetryTime)
				{
					PendingRequests.Clear();
					_nextGlobalRequestRetryTime = Time.unscaledTime + 5f;
				}
				ArenaLeaderboardCategory[] displayOrder = ArenaLeaderboardBoardPolicy.DisplayOrder;
				foreach (ArenaLeaderboardCategory category in displayOrder)
				{
					RequestIfMissing(leaderboardRequested, ArenaLeaderboardBoardPolicy.Key(category, ChallengeMode.BiomeLadder));
					RequestIfMissing(leaderboardRequested, ArenaLeaderboardBoardPolicy.Key(category, ChallengeMode.StarLadder));
				}
			}
		}

		private static void RequestIfMissing(Action<LeaderboardKey> request, LeaderboardKey key)
		{
			string text = CacheKey(key);
			if (!CachedEntries.ContainsKey(text) && PendingRequests.Add(text))
			{
				request(key);
			}
		}

		private static bool HasCompleteBoardCache()
		{
			ArenaLeaderboardCategory[] displayOrder = ArenaLeaderboardBoardPolicy.DisplayOrder;
			foreach (ArenaLeaderboardCategory category in displayOrder)
			{
				if (!CachedEntries.ContainsKey(CacheKey(ArenaLeaderboardBoardPolicy.Key(category, ChallengeMode.BiomeLadder))) || !CachedEntries.ContainsKey(CacheKey(ArenaLeaderboardBoardPolicy.Key(category, ChallengeMode.StarLadder))))
				{
					return false;
				}
			}
			return true;
		}

		private void EnsureTextMeshes()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_headerFront != (Object)null || GUIManager.IsHeadless() || GUIManager.Instance == null)
			{
				return;
			}
			Font averiaSerifBold = GUIManager.Instance.AveriaSerifBold;
			Font averiaSerif = GUIManager.Instance.AveriaSerif;
			if (!((Object)(object)averiaSerifBold == (Object)null) && !((Object)(object)averiaSerif == (Object)null))
			{
				_headerFront = CreateText("HeaderFront", new Vector3(0f, 3.72f, -0.151f), (TextAnchor)4, (TextAlignment)1, averiaSerifBold, 0.036f, 72);
				_taglineFront = CreateText("TaglineFront", new Vector3(0f, 3.42f, -0.151f), (TextAnchor)4, (TextAlignment)1, averiaSerif, 0.024f, 48);
				float sectionWidth = ArenaLeaderboardBoardPolicy.SectionWidth;
				for (int i = 0; i < ArenaLeaderboardBoardPolicy.DisplayOrder.Length; i++)
				{
					ArenaLeaderboardCategory category = ArenaLeaderboardBoardPolicy.DisplayOrder[i];
					float num = -8.6625f + ((float)i + 0.5f) * sectionWidth;
					AddSection(category, category.ToString(), num, num - sectionWidth / 4f, num + sectionWidth / 4f, 3.08f, averiaSerifBold, -0.151f);
				}
			}
		}

		private void AddSection(ArenaLeaderboardCategory category, string name, float centerX, float biomeX, float starX, float topY, Font bold, float face)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			float num = ArenaLeaderboardBoardPolicy.SectionWidth / 2.475f;
			_sections.Add(new BoardSection
			{
				Category = category,
				Heading = CreateText(name + "Heading", new Vector3(centerX, topY, face), (TextAnchor)4, (TextAlignment)1, bold, 0.022f * num, 46),
				BiomeTitle = CreateText(name + "BiomeTitle", new Vector3(biomeX, topY - 0.21f, face), (TextAnchor)1, (TextAlignment)1, bold, 0.02f * num, 38),
				BiomeEntries = CreateText(name + "BiomeEntries", new Vector3(biomeX, topY - 0.43f, face), (TextAnchor)1, (TextAlignment)1, bold, 0.02f * num, 38, 0.52f),
				StarTitle = CreateText(name + "StarTitle", new Vector3(starX, topY - 0.21f, face), (TextAnchor)1, (TextAlignment)1, bold, 0.02f * num, 38),
				StarEntries = CreateText(name + "StarEntries", new Vector3(starX, topY - 0.43f, face), (TextAnchor)1, (TextAlignment)1, bold, 0.02f * num, 38, 0.52f)
			});
		}

		private TextMesh CreateText(string name, Vector3 position, TextAnchor anchor, TextAlignment alignment, Font font, float characterSize, int fontSize, float lineSpacing = 0.82f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.layer = ((Component)this).gameObject.layer;
			val.transform.SetParent(((Component)this).transform, false);
			val.transform.localPosition = position;
			val.transform.localRotation = Quaternion.identity;
			TextMesh obj = val.AddComponent<TextMesh>();
			obj.font = font;
			obj.fontSize = fontSize;
			obj.characterSize = characterSize;
			obj.anchor = anchor;
			obj.alignment = alignment;
			obj.color = Color.white;
			obj.richText = true;
			obj.lineSpacing = lineSpacing;
			MeshRenderer component = val.GetComponent<MeshRenderer>();
			((Renderer)component).sharedMaterial = font.material;
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			return obj;
		}

		private void RenderBoard()
		{
			EnsureTextMeshes();
			if ((Object)(object)_headerFront == (Object)null)
			{
				return;
			}
			_headerFront.text = "<color=#F4D58A><b>HALL OF CHAMPIONS</b></color>";
			_taglineFront.text = "<color=#CFA65C>—  RECORDS OF VALOR  •  TOP FIVE  —</color>";
			foreach (BoardSection section in _sections)
			{
				section.Heading.text = "<color=#E2B35D><b>★  " + ArenaLeaderboardBoardPolicy.Label(section.Category).ToUpperInvariant() + "  ★</b></color>";
				section.BiomeTitle.text = "<color=#E8CC91><b>BIOME LADDER</b></color>";
				section.StarTitle.text = "<color=#E8CC91><b>STAR LADDER</b></color>";
				LeaderboardKey key = ArenaLeaderboardBoardPolicy.Key(section.Category, ChallengeMode.BiomeLadder);
				LeaderboardKey key2 = ArenaLeaderboardBoardPolicy.Key(section.Category, ChallengeMode.StarLadder);
				section.BiomeEntries.text = BuildColumn(CachedEntries.TryGetValue(CacheKey(key), out var value) ? value : null);
				section.StarEntries.text = BuildColumn(CachedEntries.TryGetValue(CacheKey(key2), out var value2) ? value2 : null);
			}
		}

		private static string BuildColumn(List<LeaderboardEntry> entries)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (entries == null)
			{
				return stringBuilder.Append("<color=#D9C7A5>Loading records...</color>").ToString();
			}
			if (entries.Count == 0)
			{
				return stringBuilder.Append("<color=#D9C7A5>— No completed runs —</color>").ToString();
			}
			for (int i = 0; i < entries.Count && i < 5; i++)
			{
				LeaderboardEntry leaderboardEntry = entries[i];
				string text = (string.IsNullOrWhiteSpace(leaderboardEntry.PlayerName) ? "Unknown" : leaderboardEntry.PlayerName.Trim());
				text = text.Replace('<', '‹').Replace('>', '›');
				if (text.Length > 9)
				{
					text = text.Substring(0, 8) + "…";
				}
				stringBuilder.Append("<color=").Append(i switch
				{
					2 => "#D28A55", 
					1 => "#D9E0E8", 
					0 => "#FFD36A", 
					_ => "#FFFFFF", 
				}).Append("><b>")
					.Append(i + 1)
					.Append(". ")
					.Append(text)
					.Append("  ")
					.Append(ArenaLeaderboardBoardPolicy.FormatDuration(leaderboardEntry.ElapsedMilliseconds))
					.Append("</b></color>\n<size=21><color=#D9C7A5>   ")
					.Append(ArenaLeaderboardBoardPolicy.FormatCompactDate(leaderboardEntry))
					.Append("</color></size>\n");
			}
			return stringBuilder.ToString();
		}

		private void UpdateFrontTextVisibility()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Camera mainCamera = Utils.GetMainCamera();
			bool flag = (Object)(object)mainCamera == (Object)null || ((Component)this).transform.InverseTransformPoint(((Component)mainCamera).transform.position).z < 0f;
			SetTextVisible(_headerFront, flag && HasClearLineOfSight(mainCamera, _headerFront));
			SetTextVisible(_taglineFront, flag && HasClearLineOfSight(mainCamera, _taglineFront));
			foreach (BoardSection section in _sections)
			{
				bool visible = flag && HasClearLineOfSight(mainCamera, section.Heading);
				bool visible2 = flag && HasClearLineOfSight(mainCamera, section.BiomeEntries);
				bool visible3 = flag && HasClearLineOfSight(mainCamera, section.StarEntries);
				SetTextVisible(section.Heading, visible);
				SetTextVisible(section.BiomeTitle, visible2);
				SetTextVisible(section.BiomeEntries, visible2);
				SetTextVisible(section.StarTitle, visible3);
				SetTextVisible(section.StarEntries, visible3);
			}
		}

		private static bool HasClearLineOfSight(Camera camera, TextMesh text)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera == (Object)null || (Object)(object)text == (Object)null)
			{
				return (Object)(object)camera == (Object)null;
			}
			Vector3 position = ((Component)camera).transform.position;
			Vector3 val = ((Component)text).transform.position - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= 0.2f)
			{
				return true;
			}
			if (_textOcclusionMask == 0)
			{
				_textOcclusionMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "terrain", "vehicle", "piece", "viewblock" });
			}
			return !Physics.Raycast(position, val / magnitude, magnitude - 0.15f, _textOcclusionMask, (QueryTriggerInteraction)1);
		}

		private static void SetTextVisible(TextMesh text, bool visible)
		{
			Renderer val = (((Object)(object)text != (Object)null) ? ((Component)text).GetComponent<Renderer>() : null);
			if ((Object)(object)val != (Object)null && val.enabled != visible)
			{
				val.enabled = visible;
			}
		}

		private void BeginGlow()
		{
			_glowUntil = Time.unscaledTime + 3f;
			_glowCleared = false;
		}

		private void UpdateGlow()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] woodRenderers;
			if (_glowUntil - Time.unscaledTime <= 0f)
			{
				woodRenderers = _woodRenderers;
				foreach (Renderer val in woodRenderers)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.SetPropertyBlock((MaterialPropertyBlock)null);
					}
				}
				_glowCleared = true;
				return;
			}
			float num = 0.35f + 0.25f * Mathf.Sin(Time.unscaledTime * 8f);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 0.58f, 0.12f, 1f);
			woodRenderers = _woodRenderers;
			foreach (Renderer val3 in woodRenderers)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Material sharedMaterial = val3.sharedMaterial;
					_glowProperties.Clear();
					val3.GetPropertyBlock(_glowProperties);
					if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_Color"))
					{
						_glowProperties.SetColor("_Color", Color.Lerp(Color.white, val2, num));
					}
					if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_BaseColor"))
					{
						_glowProperties.SetColor("_BaseColor", Color.Lerp(Color.white, val2, num));
					}
					if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_EmissionColor"))
					{
						_glowProperties.SetColor("_EmissionColor", val2 * num);
					}
					val3.SetPropertyBlock(_glowProperties);
				}
			}
		}

		private static bool SameResults(IList<LeaderboardEntry> left, IList<LeaderboardEntry> right)
		{
			if (left == right)
			{
				return true;
			}
			if (left == null || right == null || left.Count != right.Count)
			{
				return false;
			}
			for (int i = 0; i < left.Count; i++)
			{
				if (left[i].PlayerId != right[i].PlayerId || left[i].ElapsedMilliseconds != right[i].ElapsedMilliseconds || left[i].RecordedUtc != right[i].RecordedUtc)
				{
					return false;
				}
			}
			return true;
		}

		private static string CacheKey(LeaderboardKey key)
		{
			string[] array = new string[5];
			int mode = (int)key.Mode;
			array[0] = mode.ToString(CultureInfo.InvariantCulture);
			array[1] = ":";
			mode = (int)key.CapMode;
			array[2] = mode.ToString(CultureInfo.InvariantCulture);
			array[3] = ":";
			mode = (int)key.SelectedBiome;
			array[4] = mode.ToString(CultureInfo.InvariantCulture);
			return string.Concat(array);
		}
	}
	public enum ArenaWorldObjectKind
	{
		Core,
		Sign,
		StagingMarker,
		CombatantStartMarker,
		EnemySpawnMarker,
		LeaderboardBoard
	}
	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 StagingMarkerPrefabName = "ArenaGuard_StagingMarker";

		public const string CombatantStartMarkerPrefabName = "ArenaGuard_CombatantStartMarker";

		public const string EnemySpawnMarkerPrefabName = "ArenaGuard_EnemySpawnMarker";

		public const string LeaderboardBoardPrefabName = "ArenaGuard_LeaderboardBoard";

		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 string ZdoLeaderboardCategory = "arenaguard.leaderboard_category";

		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>();

		private static Sprite _combatStartCraftingIcon;

		private static Sprite _enemySpawnCraftingIcon;

		private static readonly Dictionary<char, string[]> MarkerIconGlyphs = new Dictionary<char, string[]>
		{
			['A'] = new string[7] { "01110", "10001", "10001", "11111", "10001", "10001", "10001" },
			['N'] = new string[7] { "10001", "11001", "11001", "10101", "10011", "10011", "10001" },
			['P'] = new string[7] { "11110", "10001", "10001", "11110", "10000", "10000", "10000" },
			['R'] = new string[7] { "11110", "10001", "10001", "11110", "10100", "10010", "10001" },
			['S'] = new string[7] { "11111", "10000", "10000", "11111", "00001", "00001", "11111" },
			['T'] = new string[7] { "11111", "00100", "00100", "00100", "00100", "00100", "00100" },
			['W'] = new string[7] { "10001", "10001", "10001", "10101", "10101", "10101", "01010" }
		};

		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 Action<LeaderboardKey> LeaderboardRequested;

		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_002b: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			if (!_registered)
			{
				RequirePieceBasePrefab("guard_stone");
				RequirePieceBasePrefab("sign");
				RequireChallengeHostSources();
				RegisterLocalization();
				CustomPieceTable val = new CustomPieceTable("ArenaGuard_PieceTable", new PieceTableConfig
				{
					UseCategories = false,
					UseCustomCategories = false,
					CanRemovePieces = true
				});
				if (!PieceManager.Instance.AddPieceTable(val))
				{
					throw new InvalidOperationException("ArenaGuard could not register its admin piece table.");
				}
				CustomItem val2 = new CustomItem("ArenaGuard_AdminHammer", "Hammer");
				ConfigureAdminHammer(val2, val.PieceTable);
				if (!ItemManager.Instance.AddItem(val2))
				{
					throw new InvalidOperationException("ArenaGuard could not register its admin hammer.");
				}
				_adminHammerPrefab = val2.ItemPrefab;
				RegisterCore();
				RegisterChallengeHost();
				RegisterLeaderboardBoard();
				RegisterSign(enabled: false);
				RegisterMarker("ArenaGuard_CombatantStartMarker", "$arenaguard_combat_marker", ArenaMarkerKind.CombatantStart);
				RegisterMarker("ArenaGuard_EnemySpawnMarker", "$arenaguard_enemy_marker", ArenaMarkerKind.EnemySpawn);
				TryRegisterCompatibilityMarker("ArenaGuard_StagingMarker", "$arenaguard_staging_marker", ArenaMarkerKind.Staging);
				_registered = true;
				SubscribeAdminStatusRefresh();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Registered ArenaGuard admin hammer with Arena Core, Arena Master, Hall of Champions, 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() && CanHandleAdminVisualShortcut())
				{
					ToggleAdminSetupVisuals();
				}
			}
		}

		private static bool CanHandleAdminVisualShortcut()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Plugin.Core == null)
			{
				return false;
			}
			bool hasEquippedAdminHammer = false;
			foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
			{
				if ((Object)(object)allItem?.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "ArenaGuard_AdminHammer" && ((Humanoid)localPlayer).IsItemEquiped(allItem))
				{
					hasEquippedAdminHammer = true;
					break;
				}
			}
			return ArenaAdminVisualPolicy.ShouldHandleShortcut(hasEquippedAdminHammer, !((Character)localPlayer).IsDead() && ((Character)localPlayer).GetHealth() > 0f, ((Character)localPlayer).IsTeleporting(), ((Character)localPlayer).IsAttached(), ((Character)localPlayer).InCutscene(), Plugin.Core.Input.GameOwnsTextInput || InventoryGui.IsVisible() || Minimap.IsOpen() || Hud.IsPieceSelectionVisible() || Hud.InRadial());
		}

		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, false);
					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, false);
			}
		}

		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, false);
				}
			}
		}

		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;
			}
			_lastLocalPlayer = null;
			_nextHammerAuditTime = 0f;
			_nextGrantAttemptTime = 0f;
			ChallengeHostCharacterIds.Clear();
			ArenaLeaderboardBoardBehaviour.ResetClientState();
			LeaderboardRequested = null;
			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 = "Misc",
				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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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);
			RemoveComponentsNamed(val.PiecePrefab, "AreaMarker");
			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 || HasComponentNamed(prefab, "AreaMarker"))
			{
				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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Expected O, but got Unknown
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: 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 = false;
			component4.useGravity = false;
			component4.constraints = (RigidbodyConstraints)126;
			component3.m_persistent = true;
			RemoveComponent<CharacterDrop>(val);
			RemoveComponent<ZSyncTransform>(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 RegisterLeaderboardBoard()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			CustomPiece val = new CustomPiece("ArenaGuard_LeaderboardBoard", "sign", Piece("$arenaguard_leaderboard_board", "$arenaguard_leaderboard_board_description"));
			GameObject piecePrefab = val.PiecePrefab;
			Renderer? obj = ((IEnumerable<Renderer>)piecePrefab.GetComponentsInChildren<Renderer>(true)).FirstOrDefault((Func<Renderer, bool>)delegate(Renderer candidate)
			{
				object obj2;
				if (candidate == null)
				{
					obj2 = null;
				}
				else
				{
					Material sharedMaterial = candidate.sharedMaterial;
					obj2 = ((sharedMaterial != null) ? sharedMaterial.shader : null);
				}
				return (Object)obj2 != (Object)null;
			});
			Material val2 = ((obj != null) ? obj.sharedMaterial : null);
			if ((Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("Hall of Champions could not resolve the vanilla sign wood material.");
			}
			RemoveComponent<Sign>(piecePrefab);
			RemoveComponent<WearNTear>(piecePrefab);
			RemoveComponent<Collider>(piecePrefab);
			RemoveComponent<Renderer>(piecePrefab);
			RemoveComponent<MeshFilter>(piecePrefab);
			int num = LayerMask.NameToLayer("piece_nonsolid");
			if (num < 0)
			{
				throw new InvalidOperationException("Valheim's piece_nonsolid layer is unavailable.");
			}
			SetLayerRecursively(piecePrefab, num);
			Material material = CreateBoardMaterial(val2, "HallOfChampionsPanel", new Vector2(9f, 2f));
			Material material2 = CreateBoardMaterial(val2, "HallOfChampionsFrame", new Vector2(3f, 1f));
			CreateBoardPrimitive(piecePrefab.transform, "Board", new Vector3(0f, 2.05f, 0f), new Vector3(17.55f, 3.7f, 0.18f), material, num);
			CreateBoardPrimitive(piecePrefab.transform, "LeftPost", new Vector3(-8.6625f, 2f, -0.02f), new Vector3(0.28f, 4f, 0.24f), material2, num);
			CreateBoardPrimitive(piecePrefab.transform, "RightPost", new Vector3(8.6625f, 2f, -0.02f), new Vector3(0.28f, 4f, 0.24f), material2, num);
			CreateBoardPrimitive(piecePrefab.transform, "TopBeam", new Vector3(0f, 3.92f, -0.02f), new Vector3(17.3625f, 0.16f, 0.24f), material2, num);
			CreateBoardPrimitive(piecePrefab.transform, "BottomBeam", new Vector3(0f, 0.18f, -0.02f), new Vector3(17.3625f, 0.16f, 0.24f), material2, num);
			CreateBoardPrimitive(piecePrefab.transform, "SectionDivider", new Vector3(0f, 3.25f, -0.07f), new Vector3(17.2875f, 0.065f, 0.08f), material2, num);
			for (int num2 = 1; num2 < ArenaLeaderboardBoardPolicy.DisplayOrder.Length; num2++)
			{
				float num3 = -8.6625f + (float)num2 * ArenaLeaderboardBoardPolicy.SectionWidth;
				CreateBoardPrimitive(piecePrefab.transform, "CategoryDivider", new Vector3(num3, 1.71f, -0.07f), new Vector3(0.065f, 3.08f, 0.08f), material2, num);
				CreateBoardPrimitive(piecePrefab.transform, "DividerDiamond", new Vector3(num3, 3.25f, -0.115f), new Vector3(0.15f, 0.15f, 0.07f), material2, num).transform.localRotation = Quaternion.Euler(0f, 0f, 45f);
			}
			BoxCollider val3 = piecePrefab.AddComponent<BoxCollider>();
			val3.center = new Vector3(0f, 2f, 0f);
			val3.size = new Vector3(17.7f, 4f, 0.55f);
			((Collider)val3).isTrigger = true;
			ZNetView component = piecePrefab.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_persistent = true;
			}
			Piece component2 = piecePrefab.GetComponent<Piece>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_groundPiece = true;
				component2.m_groundOnly = true;
				component2.m_clipGround = true;
				component2.m_noInWater = false;
			}
			ArenaLeaderboardBoardBehaviour board = AddWorldBehaviour<ArenaLeaderboardBoardBehaviour>(piecePrefab, ArenaWorldObjectKind.LeaderboardBoard);
			ValidateLeaderboardBoardPrefab(piecePrefab, board, val3);
			AddPiece(val);
		}

		private static Material CreateBoardMaterial(Material source, string name, Vector2 textureScale)
		{
			//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_000e: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source)
			{
				name = name
			};
			if (val.HasProperty("_MainTex"))
			{
				val.SetTextureScale("_MainTex", textureScale);
			}
			if (val.HasProperty("_BaseMap"))
			{
				val.SetTextureScale("_BaseMap", textureScale);
			}
			return val;
		}

		private static GameObject CreateBoardPrimitive(Transform parent, string name, Vector3 localPosition, Vector3 localScale, Material material, int layer)
		{
			//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((PrimitiveType)3);
			((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>();
			if ((Object)(object)component2 == (Object)null)
			{
				throw new InvalidOperationException("Hall of Champions could not create its wood renderer.");
			}
			int count = Math.Max(1, component2.sharedMaterials.Length);
			component2.sharedMaterials = Enumerable.Repeat<Material>(material, count).ToArray();
			return obj;
		}

		private static void ValidateLeaderboardBoardPrefab(GameObject prefab, ArenaLeaderboardBoardBehaviour board, BoxCollider interaction)
		{
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			Renderer[] componentsInChildren2 = prefab.GetComponentsInChildren<Renderer>(true);
			ZNetView component = prefab.GetComponent<ZNetView>();
			Piece component2 = prefab.GetComponent<Piece>();
			int num = prefab.GetComponentsInChildren<MonoBehaviour>(true).Count((MonoBehaviour val) => val is Hoverable);
			if ((Object)(object)board == (Object)null || (Object)(object)component == (Object)null || !component.m_persistent || (Object)(object)component2?.m_icon == (Object)null || componentsInChildren.Length != 1 || (object)componentsInChildren[0] != interaction || !((Collider)interaction).isTrigger || componentsInChildren2.Length < 14 || componentsInChildren2.Any((Renderer renderer) => (Object)(object)((renderer != null) ? renderer.sharedMaterial : null) == (Object)null) || num != 1)
			{
				throw new InvalidOperationException("Hall of Champions requires persistent state, a framed wood display, and one trigger-only hover surface.");
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Validated persistent one-sided Hall of Champions grand leaderboard board.");
			}
		}

		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>();
			ZSyncTransform component6 = prefab.GetComponent<ZSyncTransform>();
			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)component6 != (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-dynamic body, disabled AI, non-solid colliders, one interaction bubble, and no ZSyncTransform on its frozen body.");
			}
			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, zSyncTransform=False."));
			}
		}

		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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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 (markerKind != ArenaMarkerKind.CombatantStart && markerKind != ArenaMarkerKind.EnemySpawn)
			{
				if (val2 == null)
				{
					icon = null;
				}
				else
				{
					ItemData itemData = val2.m_itemData;
					icon = ((itemData != null) ? itemData.GetIcon() : null);
				}
			}
			else
			{
				icon = CreateMarkerCraftingIcon(markerKind);
			}
			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 Sprite CreateMarkerCraftingIcon(ArenaMarkerKind markerKind)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_0198: 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)
			bool flag = markerKind == ArenaMarkerKind.CombatantStart;
			Sprite val = (flag ? _combatStartCraftingIcon : _enemySpawnCraftingIcon);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			string text = (flag ? "START" : "SPAWN");
			Color32 color = (flag ? new Color32((byte)25, (byte)205, byte.MaxValue, byte.MaxValue) : new Color32(byte.MaxValue, (byte)55, (byte)45, byte.MaxValue));
			Color32 color2 = default(Color32);
			((Color32)(ref color2))..ctor((byte)20, (byte)24, (byte)28, (byte)238);
			Color32 color3 = default(Color32);
			((Color32)(ref color3))..ctor((byte)245, (byte)238, (byte)214, byte.MaxValue);
			Color32[] array = (Color32[])(object)new Color32[6400];
			FillMarkerIconRect(array, 80, 2, 2, 76, 76, color2);
			FillMarkerIconRect(array, 80, 2, 2, 76, 3, color);
			FillMarkerIconRect(array, 80, 2, 75, 76, 3, color);
			FillMarkerIconRect(array, 80, 2, 2, 3, 76, color);
			FillMarkerIconRect(array, 80, 75, 2, 3, 76, color);
			int num = text.Length * 5 * 2 + (text.Length - 1) * 2;
			int num2 = (80 - num) / 2;
			int y = 33;
			for (int i = 0; i < text.Length; i++)
			{
				DrawMarkerIconGlyph(array, 80, text[i], num2 + i * 6 * 2, y, 2, color3);
			}
			Texture2D val2 = new Texture2D(80, 80, (TextureFormat)4, false)
			{
				name = "ArenaGuard_" + text + "_Icon",
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			val2.SetPixels32(array);
			val2.Apply(false, true);
			Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, 80f, 80f), new Vector2(0.5f, 0.5f), 80f);
			((Object)val3).name = ((Object)val2).name;
			if (flag)
			{
				_combatStartCraftingIcon = val3;
			}
			else
			{
				_enemySpawnCraftingIcon = val3;
			}
			return val3;
		}

		private static void FillMarkerIconRect(Color32[] pixels, int textureWidth, int x, int y, int width, int height, Color32 color)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			for (int i = y; i < y + height; i++)
			{
				for (int j = x; j < x + width; j++)
				{
					pixels[i * textureWidth + j] = color;
				}
			}
		}

		private static void DrawMarkerIconGlyph(Color32[] pixels, int textureWidth, char glyph, int x, int y, int scale, Color32 color)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!MarkerIconGlyphs.TryGetValue(glyph, out var value))
			{
				return;
			}
			for (int i = 0; i < value.Length; i++)
			{
				for (int j = 0; j < value[i].Length; j++)
				{
					if (value[i][j] == '1')
					{
						FillMarkerIconRect(pixels, textureWidth, x + j * scale, y + (value.Length - 1 - i) * scale, scale, scale, color);
					}
				}
			}
		}

		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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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), 
				_ => 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, 
				_ => throw new ArgumentOutOfRangeException("markerKind", markerKind, null), 
			};
		}

		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 RemoveComponentsNamed(GameObject prefab, string typeName)
		{
			Component[] componentsInChildren = prefab.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static bool HasComponentNamed(GameObject prefab, string typeName)
		{
			Component[] componentsInChildren = prefab.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName)
				{
					return true;
				}
			}
			return false;
		}

		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_staging_marker"] = "Staging Position",
				["arenaguard_combat_marker"] = "Combat Start Position",
				["arenaguard_enemy_marker"] = "Enemy Spawn 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_leaderboard_board"] = "Hall of Champions",
				["arenaguard_leaderboard_board_description"] = "A grand one-sided display of every biome and Gauntlet top five.",
				["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."
			};
			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";

		public float GetHoverOffset()
		{
			return 0f;
		}

		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);
			Component[] componentsInChildren = ((Component)this).GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "AreaMarker")
				{
					Object.Destroy((Object)(object)val);
				}
			}
			_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;
				ApplyAdminVisibili