Decompiled source of AdminManager v1.0.2

AdminManager\AdminManager.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using AdminManager.Patches;
using AdminManager.UI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[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("AdminManager")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("AdminManager")]
[assembly: AssemblyTitle("AdminManager")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
}
namespace AdminManager
{
	[BepInPlugin("adminmanager", "Admin Manager", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class InvisibleVisual
		{
			public Player Player;

			public readonly Dictionary<Renderer, bool> Renderers = new Dictionary<Renderer, bool>();

			public readonly Dictionary<Light, bool> Lights = new Dictionary<Light, bool>();

			public readonly Dictionary<AudioSource, float> Sounds = new Dictionary<AudioSource, float>();
		}

		private sealed class ClientGate
		{
			public ZNet Net;

			public ZNetPeer Peer;

			public string Nonce;

			public bool Required;

			public bool Verified;

			public bool Rejected;

			public bool Admitted;

			public ZPackage Pending;

			public float Deadline;

			public float DisconnectAt;
		}

		private sealed class KnownPlayer
		{
			public long Id;

			public string Name;

			public string Host;

			public long LastSeen;

			public bool Online;
		}

		private sealed class PendingTeleport
		{
			public long Requester;

			public long Peer;

			public string Description;

			public float Expires;
		}

		private sealed class OwnedFreeze
		{
			public Player Player;

			public Rigidbody Body;

			public RigidbodyConstraints Constraints;

			public Vector3 Position;

			public Quaternion Rotation;
		}

		private sealed class FreezeRequest
		{
			public long Owner;

			public long Requester;

			public bool Frozen;

			public bool Confirmed;

			public float Expires;
		}

		private sealed class ItemToken
		{
			public ZDOID Character;

			public Inventory Inventory;

			public ItemData Item;

			public string Fingerprint;

			public float Expires;
		}

		private sealed class InventoryAccess
		{
			public ZDOID Character;

			public int ClientRequest;

			public float Expires;

			public readonly HashSet<string> Tokens = new HashSet<string>();
		}

		private sealed class ItemOperation
		{
			public long Requester;

			public long Owner;

			public int ClientRequest;

			public float Expires;
		}

		private sealed class InventoryEntry
		{
			public string Prefab;

			public string Name;

			public int Stack;

			public int X;

			public int Y;

			public bool Equipped;

			public string Token = "";
		}

		private sealed class InventorySnapshot
		{
			public int Width;

			public int Height;

			public readonly List<InventoryEntry> Items = new List<InventoryEntry>();
		}

		private sealed class InventoryRequest
		{
			public long Requester;

			public int ClientRequest;

			public ZDOID Character;

			public long Peer;

			public float Expires;
		}

		private sealed class PlayerPanelAction
		{
			public string Label;

			public Action Run;

			public bool Enabled;

			public bool Active;

			public string Icon;

			public PlayerPanelAction(string label, Action run, bool enabled = true, bool active = false, string icon = null)
			{
				Label = label;
				Run = run;
				Enabled = enabled;
				Active = active;
				Icon = icon;
			}
		}

		private sealed class CardDef
		{
			public readonly string Label;

			public readonly string Command;

			public readonly Func<bool> State;

			public readonly bool Toggle;

			public readonly string Perm;

			public CardDef(string label, string command, Func<bool> state, bool toggle, string perm)
			{
				Label = label;
				Command = command;
				State = state;
				Toggle = toggle;
				Perm = perm;
			}
		}

		private sealed class QuarantinePending
		{
			public long Requester;

			public bool Active;

			public float Expires;
		}

		private sealed class QuarantineSnapshot
		{
			public int Revision;

			public bool Local;

			public readonly HashSet<ZDOID> Characters = new HashSet<ZDOID>();

			public readonly HashSet<long> Profiles = new HashSet<long>();
		}

		private sealed class ChickenVisual
		{
			public Player Player;

			public GameObject Model;

			public Animator Animator;

			public readonly Dictionary<Renderer, bool> Hidden = new Dictionary<Renderer, bool>();

			public readonly List<int> SpeedParameters = new List<int>();
		}

		private sealed class ResourceState
		{
			public long Peer;

			public int CarryMode;

			public float Capacity;

			public bool UnlimitedStamina;
		}

		private sealed class WorldChoice
		{
			public string Id;

			public string Name;

			public string[] Keys = Array.Empty<string>();
		}

		private sealed class WorldSetting
		{
			public string Id;

			public string Name;

			public string Default;

			public string Current;

			public List<WorldChoice> Choices = new List<WorldChoice>();
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__11_0;

			public static Predicate<PlayerInfo> <>9__27_0;

			public static Func<KeyValuePair<string, List<long>>, string> <>9__37_0;

			public static Func<long, string> <>9__37_1;

			public static Func<char, bool> <>9__55_0;

			public static Comparison<KnownPlayer> <>9__103_0;

			public static Comparison<KnownPlayer> <>9__119_0;

			public static Func<bool> <>9__301_6;

			public static Func<string, string> <>9__429_0;

			public static Predicate<ZDOID> <>9__440_0;

			public static Func<WorldChoice, IEnumerable<string>> <>9__512_0;

			public static Func<string, string> <>9__513_1;

			public static Func<string, string> <>9__513_2;

			public static Func<string, string> <>9__514_0;

			public static Func<string, string> <>9__514_4;

			public static Predicate<string> <>9__514_1;

			public static Func<WorldSetting, IEnumerable<string>> <>9__515_3;

			public static Func<string, string> <>9__515_1;

			public static Func<string, string> <>9__515_2;

			public static Func<string, bool> <>9__519_0;

			public static Func<string, string> <>9__519_1;

			public static Func<KeyValuePair<string, string>, string> <>9__528_0;

			public static Func<WorldChoice, bool> <>9__535_1;

			public static Func<WorldChoice, bool> <>9__535_2;

			internal void <InitializeInvisibility>b__11_0(ConsoleEventArgs args)
			{
				if (args.Length != 1)
				{
					args.Context.AddString("Usage: aminvisible");
				}
				else if ((Object)(object)m_instance != (Object)null)
				{
					m_instance.RequestInvisibility();
				}
			}

			internal bool <InvisibleMapPostfix>b__27_0(PlayerInfo p)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				return m_instance.m_invisibleCharacters.Contains(p.m_characterID);
			}

			internal string <SerializeChickenEggTimes>b__37_0(KeyValuePair<string, List<long>> e)
			{
				return e.Key;
			}

			internal string <SerializeChickenEggTimes>b__37_1(long t)
			{
				return t.ToString(CultureInfo.InvariantCulture);
			}

			internal bool <ValidBuildFingerprint>b__55_0(char c)
			{
				if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
				{
					if (c >= 'A')
					{
						return c <= 'F';
					}
					return false;
				}
				return true;
			}

			internal int <DrawOnlineTeleportSelector>b__103_0(KnownPlayer a, KnownPlayer b)
			{
				return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
			}

			internal int <DrawOfflineTab>b__119_0(KnownPlayer a, KnownPlayer b)
			{
				return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
			}

			internal bool <DrawCommandGrid>b__301_6()
			{
				return InvisibleCharacter((Character)(object)Player.m_localPlayer);
			}

			internal string <SerializeQuarantineAccounts>b__429_0(string a)
			{
				return a;
			}

			internal bool <BroadcastQuarantine>b__440_0(ZDOID id)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (ZDOMan.instance != null)
				{
					return ZDOMan.instance.GetZDO(id) == null;
				}
				return true;
			}

			internal IEnumerable<string> <ManagedWorldKeys>b__512_0(WorldChoice c)
			{
				return c.Keys;
			}

			internal string <DetectWorldChoice>b__513_1(string k)
			{
				return k.ToLowerInvariant();
			}

			internal string <DetectWorldChoice>b__513_2(string k)
			{
				return k.ToLowerInvariant();
			}

			internal string <BuildWorldKeyChanges>b__514_0(string k)
			{
				return k.ToLowerInvariant();
			}

			internal string <BuildWorldKeyChanges>b__514_4(string k)
			{
				return k.ToLowerInvariant();
			}

			internal bool <BuildWorldKeyChanges>b__514_1(string k)
			{
				return WorldKeyName(k) == "preset";
			}

			internal IEnumerable<string> <WorldSettingsFingerprint>b__515_3(WorldSetting s)
			{
				return ManagedWorldKeys(s);
			}

			internal string <WorldSettingsFingerprint>b__515_1(string k)
			{
				return k.ToLowerInvariant();
			}

			internal string <WorldSettingsFingerprint>b__515_2(string k)
			{
				return k;
			}

			internal bool <CaptureWorldSlider>b__519_0(string k)
			{
				return !string.IsNullOrWhiteSpace(k);
			}

			internal string <CaptureWorldSlider>b__519_1(string k)
			{
				return k.Trim().ToLowerInvariant();
			}

			internal string <RPC_SetWorldSettings>b__528_0(KeyValuePair<string, string> c)
			{
				return c.Key + "=" + c.Value;
			}

			internal bool <DrawWorldSettingCard>b__535_1(WorldChoice c)
			{
				return c.Id == "on";
			}

			internal bool <DrawWorldSettingCard>b__535_2(WorldChoice c)
			{
				return c.Id == "off";
			}
		}

		private readonly Dictionary<long, ZDOID> m_invisiblePeers = new Dictionary<long, ZDOID>();

		private readonly HashSet<ZDOID> m_invisibleCharacters = new HashSet<ZDOID>();

		private readonly Dictionary<ZDOID, InvisibleVisual> m_invisibleVisuals = new Dictionary<ZDOID, InvisibleVisual>();

		private int m_invisibleRevision;

		private int m_receivedInvisibleRevision = -1;

		private float m_nextInvisibleSync;

		private bool m_restorePublicPosition;

		private bool m_previousPublicPosition;

		private const int ChickenEggLimit = 3;

		private static readonly long ChickenEggWindow = TimeSpan.FromMinutes(10.0).Ticks;

		private readonly Dictionary<string, List<long>> m_chickenEggTimes = new Dictionary<string, List<long>>(StringComparer.Ordinal);

		private readonly Dictionary<string, float> m_chickenEggAttempts = new Dictionary<string, float>(StringComparer.Ordinal);

		private bool m_chickenEggStorageReady;

		private float m_nextChickenEggRequest;

		private const int ClientHandshakeProtocol = 1;

		private ConfigEntry<bool> m_requireMatchingClient;

		private string m_buildFingerprint = "";

		private string m_connectionNotice = "";

		private readonly Dictionary<ZRpc, ClientGate> m_clientGates = new Dictionary<ZRpc, ClientGate>();

		private MethodInfo m_nativePeerInfo;

		private string m_feedback = "";

		private float m_feedbackUntil;

		private bool m_feedbackError;

		private float m_actionRadius = 30f;

		private float m_nextRosterScan;

		private float m_nextRosterSave;

		private float m_nextRosterRequest;

		private long m_offlineSelection;

		private long m_teleportSelection;

		private string m_rosterSearch = "";

		private Vector2 m_rosterScroll;

		private readonly Dictionary<long, KnownPlayer> m_knownPlayers = new Dictionary<long, KnownPlayer>();

		private readonly Dictionary<int, PendingTeleport> m_pendingTeleports = new Dictionary<int, PendingTeleport>();

		private int m_nextTeleport;

		private float m_nextWorldSave;

		private readonly Dictionary<ZDOID, OwnedFreeze> m_ownedFreezes = new Dictionary<ZDOID, OwnedFreeze>();

		private readonly Dictionary<ZDOID, FreezeRequest> m_serverFreezes = new Dictionary<ZDOID, FreezeRequest>();

		private float m_nextFreezeAudit;

		private readonly Dictionary<string, ItemToken> m_itemTokens = new Dictionary<string, ItemToken>();

		private readonly Dictionary<long, InventoryAccess> m_inventoryAccess = new Dictionary<long, InventoryAccess>();

		private readonly Dictionary<int, ItemOperation> m_itemOperations = new Dictionary<int, ItemOperation>();

		private int m_nextItemOperation;

		private InventoryEntry m_selectedInventoryItem;

		private string m_itemAmount = "1";

		private bool m_itemConfirm;

		private bool m_itemDelete;

		private bool m_itemActionPending;

		private float m_itemClientDeadline;

		private readonly Dictionary<int, InventoryRequest> m_inventoryRequests = new Dictionary<int, InventoryRequest>();

		private readonly Dictionary<long, float> m_inventoryCooldowns = new Dictionary<long, float>();

		private int m_nextInventoryRequest;

		private long m_inventoryTarget;

		private ZDOID m_inventoryCharacter = ZDOID.None;

		private int m_inventoryClientRequest;

		private InventorySnapshot m_inventoryPreview;

		private float m_inventoryReceived;

		private int m_inventoryColumnPage;

		private GUIStyle m_playerControlStyle;

		private GUIStyle m_playerCardLabel;

		public const string PluginGuid = "adminmanager";

		public const string PluginVersion = "1.0.2";

		internal static ManualLogSource Log;

		private bool m_show;

		private ConfigEntry<KeyboardShortcut> m_toggleKey;

		private int m_tab;

		private int m_selectedPlayerInstanceId;

		private RenderTexture m_previewRT;

		private Camera m_previewCamera;

		private GameObject m_previewCameraGO;

		private int m_previewPlayerInstanceId;

		private float m_previewYaw;

		private float m_previewPitch = 12f;

		private float m_previewDistance = 4.2f;

		private const float PreviewTargetHeight = 1.1f;

		private float m_cellW = 120f;

		private float m_cellH = 120f;

		private float m_pCellW = 96f;

		private float m_skipHours = 6f;

		private Harmony m_harmony;

		private FallbackSpriteFactory m_sprites;

		private Dictionary<string, Texture2D> m_icons;

		private Dictionary<string, string> m_iconPieceMap;

		private Dictionary<string, string> m_iconStatusMap;

		private Dictionary<string, string> m_uiSpriteMap;

		private Dictionary<string, string> m_uiOverlayMap;

		private readonly HashSet<string> m_uiIcons = new HashSet<string>();

		private readonly HashSet<string> m_uiOverlayDone = new HashSet<string>();

		private bool m_uiIconsLoaded;

		private int m_uiIconAttempts;

		private Dictionary<string, string> m_iconItemMap;

		private bool m_gameIconsLoaded;

		private GUIStyle m_windowStyle;

		private GUIStyle m_buttonStyle;

		private GUIStyle m_cardStyle;

		private GUIStyle m_centerLabel;

		private GUIStyle m_headerStyle;

		private GUIStyle m_tabActive;

		private GUIStyle m_tabIdle;

		private GUIStyle m_sectionStyle;

		private GUIStyle m_listPanelStyle;

		private GUIStyle m_dividerStyle;

		private Rect m_window = new Rect(20f, 20f, 360f, 520f);

		private Vector2 m_scroll;

		private readonly Vector2[] m_tabScroll = (Vector2[])(object)new Vector2[6];

		private int m_scrollTab;

		private bool m_rpcRegistered;

		private ZRoutedRpc m_registeredRpc;

		private float m_nextPermRequest;

		private int m_lastPeerCount = -1;

		private readonly Dictionary<long, Dictionary<string, bool>> m_state = new Dictionary<long, Dictionary<string, bool>>();

		private readonly Dictionary<long, bool> m_allowed = new Dictionary<long, bool>();

		private static readonly HashSet<long> m_serverAllowed = new HashSet<long>();

		private static readonly List<string> m_bans = new List<string>();

		private static int m_bansVersion;

		private bool m_bansRequested;

		private static readonly Dictionary<string, bool> m_permGlobal = new Dictionary<string, bool>();

		private static readonly Dictionary<long, HashSet<string>> m_permPlayers = new Dictionary<long, HashSet<string>>();

		private static readonly HashSet<long> m_admins = new HashSet<long>();

		private static readonly Dictionary<string, string> m_banNames = new Dictionary<string, string>();

		private static bool m_permsLoaded;

		private static readonly List<string> PermKeys = new List<string>
		{
			"god", "fly", "freefly", "ghost", "nocost", "freebuild", "heal", "repairall", "removedrops", "clearstatus",
			"tame", "stopevent", "sleep", "killall", "killenemies", "time", "kill", "respawn", "kick", "ban",
			"carryweight", "unlimitedweight", "unlimitedstamina"
		};

		private static readonly Dictionary<string, string> PermLabels = new Dictionary<string, string>
		{
			{ "god", "God" },
			{ "fly", "Fly" },
			{ "freefly", "Free Fly" },
			{ "ghost", "Ghost" },
			{ "nocost", "No Cost" },
			{ "freebuild", "Build Cam" },
			{ "heal", "Heal" },
			{ "repairall", "Repair" },
			{ "removedrops", "Remove Drops" },
			{ "clearstatus", "Clear Status" },
			{ "tame", "Tame" },
			{ "stopevent", "Stop Event" },
			{ "sleep", "Sleep" },
			{ "killall", "Kill All" },
			{ "killenemies", "Kill Enemies" },
			{ "time", "Skip Time" },
			{ "kill", "Kill" },
			{ "respawn", "Respawn" },
			{ "kick", "Kick" },
			{ "ban", "Ban" },
			{ "carryweight", "Carry Cap" },
			{ "unlimitedweight", "Unlimited Carry" },
			{ "unlimitedstamina", "Unlimited Stamina" }
		};

		private int m_permPlayerInstanceId;

		private bool m_permsRequested;

		private static Plugin m_instance;

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

		private readonly HashSet<ZDOID> m_quarantineBots = new HashSet<ZDOID>();

		private readonly HashSet<ZDOID> m_quarantineCharacters = new HashSet<ZDOID>();

		private readonly HashSet<long> m_quarantineProfiles = new HashSet<long>();

		private readonly Dictionary<ZDOID, ChickenVisual> m_chickenVisuals = new Dictionary<ZDOID, ChickenVisual>();

		private bool m_localQuarantined;

		private float m_nextQuarantineSync;

		private float m_nextQuarantineVisual;

		private float m_nextQuarantineVisualWarning;

		private int m_quarantineRevision;

		private int m_receivedQuarantineRevision = -1;

		private readonly Dictionary<long, QuarantinePending> m_quarantinePending = new Dictionary<long, QuarantinePending>();

		private static readonly HashSet<string> QuarantineBlockedButtons = new HashSet<string>(StringComparer.Ordinal)
		{
			"Inventory", "JoyInventory", "Map", "JoyMap", "Use", "JoyUse", "Attack", "JoyAttack", "SecondaryAttack", "JoySecondaryAttack",
			"Block", "JoyBlock", "Remove", "JoyRemove", "BuildMenu", "JoyBuildMenu", "OpenRadial", "OpenEmote", "JoyRadial", "GP",
			"JoyGP", "Sit", "Hide", "AutoPickup", "JoyAutoPickup", "RadialSecondaryInteract", "JoyRadialSecondaryInteract", "Hotbar1", "Hotbar2", "Hotbar3",
			"Hotbar4", "Hotbar5", "Hotbar6", "Hotbar7", "Hotbar8"
		};

		private readonly Dictionary<long, ResourceState> m_resourceStates = new Dictionary<long, ResourceState>();

		private ResourceState m_localResources = new ResourceState();

		private string m_carryCapacityText = "1000";

		private float m_nextResourceAudit;

		private readonly Dictionary<string, WorldSetting> m_worldCatalog = new Dictionary<string, WorldSetting>(StringComparer.Ordinal);

		private readonly List<WorldSetting> m_worldView = new List<WorldSetting>();

		private readonly Dictionary<string, string> m_worldDraft = new Dictionary<string, string>(StringComparer.Ordinal);

		private readonly Dictionary<long, float> m_worldRequestTimes = new Dictionary<long, float>();

		private string m_worldFingerprint = "";

		private float m_nextWorldRefresh;

		private float m_nextWorldCatalogScan;

		private float m_worldApplyDeadline;

		private bool m_worldStale;

		private bool m_worldConfirm;

		private bool m_worldApplyPending;

		private bool m_worldSavePending;

		private MethodInfo m_addWorldKey;

		private MethodInfo m_removeWorldKey;

		private MethodInfo m_sendWorldKeys;

		private static readonly string[] WorldSettingOrder = new string[9] { "resources", "combat", "raids", "deathpenalty", "portals", "passive", "freebuild", "map", "playerraids" };

		private GUIStyle PlayerControlStyle
		{
			get
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Expected O, but got Unknown
				//IL_0023: 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_0037: Expected O, but got Unknown
				if (m_playerControlStyle == null)
				{
					m_playerControlStyle = new GUIStyle(m_buttonStyle)
					{
						margin = new RectOffset(0, 0, 0, 0),
						fontSize = 12,
						alignment = (TextAnchor)4
					};
				}
				return m_playerControlStyle;
			}
		}

		private static bool LocalQuarantined
		{
			get
			{
				if ((Object)(object)m_instance != (Object)null)
				{
					return m_instance.m_localQuarantined;
				}
				return false;
			}
		}

		private static bool InvisibleCharacter(Character player)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (player is Player && (Object)(object)m_instance != (Object)null)
			{
				return m_instance.m_invisibleCharacters.Contains(player.GetZDOID());
			}
			return false;
		}

		private static IEnumerable<Tuple<Type, string, string>> InvisiblePatchTargets()
		{
			yield return Tuple.Create(typeof(EnemyHud), "TestShow", "InvisibleHudPrefix");
			yield return Tuple.Create(typeof(Player), "GetHoverName", "InvisibleHoverPrefix");
			yield return Tuple.Create(typeof(Player), "GetHoverText", "InvisibleHoverPrefix");
			yield return Tuple.Create(typeof(ZNet), "SetPublicReferencePosition", "InvisiblePublicPositionPrefix");
		}

		private void InitializeInvisibility()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			foreach (Tuple<Type, string, string> item in InvisiblePatchTargets())
			{
				PatchResource(item.Item1, item.Item2, item.Item3, prefix: true);
			}
			PatchResource(typeof(ZNet), "GetOtherPublicPlayers", "InvisibleMapPostfix", prefix: false);
			PatchResource(typeof(ZNet), "UpdatePlayerList", "InvisiblePlayerListPostfix", prefix: false);
			object obj = <>c.<>9__11_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					if (args.Length != 1)
					{
						args.Context.AddString("Usage: aminvisible");
					}
					else if ((Object)(object)m_instance != (Object)null)
					{
						m_instance.RequestInvisibility();
					}
				};
				<>c.<>9__11_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("aminvisible", "Admin Manager: toggle player invisibility (admin only).", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private void RegisterInvisibility()
		{
			ZRoutedRpc.instance.Register<bool>("AdminManager_InvisibleRequest", (Action<long, bool>)RPC_InvisibleRequest);
			ZRoutedRpc.instance.Register<ZPackage>("AdminManager_InvisibleState", (Action<long, ZPackage>)RPC_InvisibleState);
		}

		private void RequestInvisibility()
		{
			if (!IsLocalAdmin() || LocalQuarantined)
			{
				Feedback("Invisibility is admin-only.", error: true);
				return;
			}
			if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				Feedback("Load a character first.", error: true);
				return;
			}
			bool flag = !InvisibleCharacter((Character)(object)Player.m_localPlayer);
			if (ZNet.instance.IsServer())
			{
				RPC_InvisibleRequest(ServerPeerId(), flag);
				return;
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_InvisibleRequest", new object[1] { flag });
		}

		private static void RPC_InvisibleRequest(long sender, bool enabled)
		{
			//IL_004a: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || DenyQuarantined(sender))
			{
				return;
			}
			if (!IsAdminSender(sender))
			{
				Reply(sender, "Invisibility is admin-only.", error: true);
				return;
			}
			ZDOID value = m_instance.InvisiblePeerCharacter(sender);
			if (((ZDOID)(ref value)).IsNone())
			{
				Reply(sender, "Your character is not ready.", error: true);
				return;
			}
			if (enabled && !m_instance.m_invisiblePeers.ContainsKey(sender) && m_instance.m_invisiblePeers.Count >= 128)
			{
				Reply(sender, "Invisibility capacity reached.", error: true);
				return;
			}
			if (enabled)
			{
				m_instance.m_invisiblePeers[sender] = value;
			}
			else
			{
				m_instance.m_invisiblePeers.Remove(sender);
			}
			m_instance.m_invisibleRevision++;
			m_instance.BroadcastInvisibility();
			Reply(sender, enabled ? "Invisible to players: body, equipment, nameplate and map marker hidden." : "Visible to players again.");
			Log.LogInfo((object)("Admin invisibility: peer=" + sender + " enabled=" + enabled));
		}

		private ZDOID InvisiblePeerCharacter(long peer)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			if (peer != ServerPeerId())
			{
				return ZNet.instance.GetPeer(peer)?.m_characterID ?? ZDOID.None;
			}
			return ZNet.instance.LocalPlayerCharacterID;
		}

		private void BroadcastInvisibility()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			m_invisibleCharacters.Clear();
			m_invisibleCharacters.UnionWith(m_invisiblePeers.Values);
			ZPackage val = new ZPackage();
			val.Write(m_invisibleRevision);
			val.Write(m_invisibleCharacters.Count);
			foreach (ZDOID invisibleCharacter in m_invisibleCharacters)
			{
				val.Write(invisibleCharacter);
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "AdminManager_InvisibleState", new object[1] { val });
			}
			UpdateInvisibleVisuals();
		}

		private static HashSet<ZDOID> ReadInvisibleCharacters(ZPackage packet, out int revision)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (packet == null || packet.Size() > 4096)
			{
				throw new ArgumentException("Invalid invisibility snapshot.");
			}
			revision = packet.ReadInt();
			int num = packet.ReadInt();
			if (revision < 0 || num < 0 || num > 128)
			{
				throw new ArgumentException("Invalid invisibility count/revision.");
			}
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			for (int i = 0; i < num; i++)
			{
				ZDOID item = packet.ReadZDOID();
				if (((ZDOID)(ref item)).IsNone() || !hashSet.Add(item))
				{
					throw new ArgumentException("Invalid invisibility character.");
				}
			}
			if (packet.GetPos() != packet.Size())
			{
				throw new ArgumentException("Trailing invisibility data.");
			}
			return hashSet;
		}

		private static void RPC_InvisibleState(long sender, ZPackage packet)
		{
			if ((Object)(object)m_instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || !IsServerMessage(sender))
			{
				return;
			}
			try
			{
				int revision;
				HashSet<ZDOID> other = ReadInvisibleCharacters(packet, out revision);
				if (revision >= m_instance.m_receivedInvisibleRevision)
				{
					m_instance.m_receivedInvisibleRevision = revision;
					m_instance.m_invisibleCharacters.Clear();
					m_instance.m_invisibleCharacters.UnionWith(other);
					m_instance.UpdateInvisibleVisuals();
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Invalid invisibility state: " + ex.Message));
			}
		}

		private void UpdateInvisibility(bool server)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!server || Time.unscaledTime < m_nextInvisibleSync)
			{
				return;
			}
			m_nextInvisibleSync = Time.unscaledTime + 1f;
			KeyValuePair<long, ZDOID>[] array = m_invisiblePeers.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<long, ZDOID> keyValuePair = array[i];
				if (!IsAdminSender(keyValuePair.Key) || !(keyValuePair.Value == InvisiblePeerCharacter(keyValuePair.Key)))
				{
					m_invisiblePeers.Remove(keyValuePair.Key);
					m_invisibleRevision++;
				}
			}
			BroadcastInvisibility();
		}

		private void UpdateInvisibleVisuals()
		{
			//IL_0056: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<ZDOID, InvisibleVisual>[] array = m_invisibleVisuals.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<ZDOID, InvisibleVisual> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Value.Player == (Object)null || !m_invisibleCharacters.Contains(keyValuePair.Key) || QuarantinedCharacter(keyValuePair.Value.Player))
				{
					RestoreInvisibleVisual(keyValuePair.Key);
				}
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer == (Object)null || !InvisibleCharacter((Character)(object)allPlayer) || QuarantinedCharacter(allPlayer))
				{
					continue;
				}
				ZDOID zDOID = ((Character)allPlayer).GetZDOID();
				if (!m_invisibleVisuals.TryGetValue(zDOID, out var value))
				{
					value = new InvisibleVisual
					{
						Player = allPlayer
					};
					m_invisibleVisuals[zDOID] = value;
				}
				Renderer[] componentsInChildren = ((Component)allPlayer).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					if (!value.Renderers.ContainsKey(val))
					{
						value.Renderers[val] = val.forceRenderingOff;
					}
					val.forceRenderingOff = true;
				}
				Light[] componentsInChildren2 = ((Component)allPlayer).GetComponentsInChildren<Light>(true);
				foreach (Light val2 in componentsInChildren2)
				{
					if (!value.Lights.ContainsKey(val2))
					{
						value.Lights[val2] = ((Behaviour)val2).enabled;
					}
					((Behaviour)val2).enabled = false;
				}
				AudioSource[] componentsInChildren3 = ((Component)allPlayer).GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource val3 in componentsInChildren3)
				{
					if (!value.Sounds.ContainsKey(val3))
					{
						value.Sounds[val3] = val3.volume;
					}
					val3.volume = 0f;
				}
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			if (InvisibleCharacter((Character)(object)Player.m_localPlayer))
			{
				if (!m_restorePublicPosition)
				{
					m_previousPublicPosition = ZNet.instance.IsReferencePositionPublic();
					m_restorePublicPosition = true;
				}
				ZNet.instance.SetPublicReferencePosition(false);
			}
			else
			{
				RestoreInvisiblePublicPosition();
			}
		}

		private void RestoreInvisibleVisual(ZDOID id)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!m_invisibleVisuals.TryGetValue(id, out var value))
			{
				return;
			}
			foreach (KeyValuePair<Renderer, bool> renderer in value.Renderers)
			{
				if ((Object)(object)renderer.Key != (Object)null)
				{
					renderer.Key.forceRenderingOff = renderer.Value;
				}
			}
			foreach (KeyValuePair<Light, bool> light in value.Lights)
			{
				if ((Object)(object)light.Key != (Object)null)
				{
					((Behaviour)light.Key).enabled = light.Value;
				}
			}
			foreach (KeyValuePair<AudioSource, float> sound in value.Sounds)
			{
				if ((Object)(object)sound.Key != (Object)null)
				{
					sound.Key.volume = sound.Value;
				}
			}
			m_invisibleVisuals.Remove(id);
		}

		private void RestoreInvisiblePublicPosition()
		{
			if (m_restorePublicPosition)
			{
				m_restorePublicPosition = false;
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					ZNet.instance.SetPublicReferencePosition(m_previousPublicPosition);
				}
			}
		}

		private void ResetInvisibility()
		{
			//IL_002d: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			m_invisiblePeers.Clear();
			m_invisibleCharacters.Clear();
			ZDOID[] array = m_invisibleVisuals.Keys.ToArray();
			foreach (ZDOID id in array)
			{
				RestoreInvisibleVisual(id);
			}
			RestoreInvisiblePublicPosition();
			m_invisibleRevision = 0;
			m_receivedInvisibleRevision = -1;
			m_nextInvisibleSync = 0f;
		}

		private static bool InvisibleHudPrefix(Character c, ref bool __result)
		{
			if (!InvisibleCharacter(c))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool InvisibleHoverPrefix(Player __instance, ref string __result)
		{
			if (!InvisibleCharacter((Character)(object)__instance))
			{
				return true;
			}
			__result = "";
			return false;
		}

		private static void InvisiblePublicPositionPrefix(ref bool pub)
		{
			if (InvisibleCharacter((Character)(object)Player.m_localPlayer))
			{
				pub = false;
			}
		}

		private static void InvisibleMapPostfix(List<PlayerInfo> playerList)
		{
			if ((Object)(object)m_instance != (Object)null)
			{
				playerList.RemoveAll((PlayerInfo p) => m_instance.m_invisibleCharacters.Contains(p.m_characterID));
			}
		}

		private static void InvisiblePlayerListPostfix(ZNet __instance)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_004a: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_instance == (Object)null || !__instance.IsServer())
			{
				return;
			}
			List<PlayerInfo> playerList = __instance.GetPlayerList();
			for (int i = 0; i < playerList.Count; i++)
			{
				PlayerInfo val = playerList[i];
				if (m_instance.m_invisibleCharacters.Contains(val.m_characterID))
				{
					val.m_publicPosition = false;
					val.m_position = Vector3.zero;
					playerList[i] = val;
				}
			}
		}

		private static void PruneChickenEggTimes(List<long> times, long now)
		{
			times.RemoveAll((long time) => time <= now - ChickenEggWindow);
		}

		private static bool ReserveChickenEgg(List<long> times, long now)
		{
			if (now > 0)
			{
				DateTime maxValue = DateTime.MaxValue;
				if (now <= maxValue.Ticks)
				{
					PruneChickenEggTimes(times, now);
					if (times.Count >= 3)
					{
						return false;
					}
					times.Add(now);
					return true;
				}
			}
			return false;
		}

		private static string SerializeChickenEggTimes(Dictionary<string, List<long>> accounts, long now)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, List<long>> item in accounts.OrderBy<KeyValuePair<string, List<long>>, string>((KeyValuePair<string, List<long>> e) => e.Key, StringComparer.Ordinal))
			{
				if (!ValidQuarantineAccount(item.Key))
				{
					throw new FormatException("Invalid egg quota account.");
				}
				PruneChickenEggTimes(item.Value, now);
				if (item.Value.Count != 0)
				{
					list.Add(Encode(item.Key) + "|" + string.Join(",", item.Value.Select((long t) => t.ToString(CultureInfo.InvariantCulture))));
				}
			}
			return string.Join("\n", list);
		}

		private static Dictionary<string, List<long>> ParseChickenEggTimes(string data, long now)
		{
			if (data == null || data.Length > 2097152)
			{
				throw new FormatException("Egg quota file is too large.");
			}
			Dictionary<string, List<long>> dictionary = new Dictionary<string, List<long>>(StringComparer.Ordinal);
			string[] array = data.Split(new char[1] { '\n' });
			foreach (string text in array)
			{
				if (string.IsNullOrWhiteSpace(text))
				{
					continue;
				}
				string[] array2 = text.Trim().Split(new char[1] { '|' });
				if (array2.Length != 2)
				{
					throw new FormatException("Invalid egg quota entry.");
				}
				string text2 = Decode(array2[0]);
				if (!ValidQuarantineAccount(text2) || dictionary.ContainsKey(text2) || dictionary.Count >= 4096)
				{
					throw new FormatException("Invalid egg quota account.");
				}
				List<long> list = new List<long>();
				string[] array3 = array2[1].Split(new char[1] { ',' });
				int num = 0;
				while (num < array3.Length)
				{
					if (long.TryParse(array3[num], NumberStyles.None, CultureInfo.InvariantCulture, out var result) && result > 0)
					{
						long num2 = result;
						DateTime maxValue = DateTime.MaxValue;
						if (num2 <= maxValue.Ticks && list.Count < 3)
						{
							list.Add(result);
							num++;
							continue;
						}
					}
					throw new FormatException("Invalid egg quota timestamp.");
				}
				PruneChickenEggTimes(list, now);
				dictionary.Add(text2, list);
			}
			return dictionary;
		}

		private void LoadEggQuotas()
		{
			m_chickenEggStorageReady = false;
			m_chickenEggTimes.Clear();
			try
			{
				string text = DataPath("quarantine_eggs");
				if (text == null)
				{
					return;
				}
				if (File.Exists(text))
				{
					foreach (KeyValuePair<string, List<long>> item in ParseChickenEggTimes(File.ReadAllText(text), DateTime.UtcNow.Ticks))
					{
						m_chickenEggTimes.Add(item.Key, item.Value);
					}
				}
				m_chickenEggStorageReady = true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Egg drops disabled: could not read the world's egg quota file. " + ex.Message));
			}
		}

		private void SaveEggQuotas(long now)
		{
			string text = DataPath("quarantine_eggs");
			if (!m_chickenEggStorageReady || text == null)
			{
				throw new InvalidOperationException("Egg quota storage is unavailable.");
			}
			string text2 = text + ".tmp";
			File.WriteAllText(text2, SerializeChickenEggTimes(m_chickenEggTimes, now));
			if (File.Exists(text))
			{
				File.Replace(text2, text, text + ".bak");
			}
			else
			{
				File.Move(text2, text);
			}
		}

		private void RegisterChickenEggs()
		{
			ZRoutedRpc.instance.Register("AdminManager_ChickenEgg", (Action<long>)RPC_ChickenEgg);
			ZRoutedRpc.instance.Register<string>("AdminManager_ChickenEggResult", (Action<long, string>)RPC_ChickenEggResult);
		}

		private void RequestChickenEgg()
		{
			if (LocalQuarantined && !((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null && !(Time.unscaledTime < m_nextChickenEggRequest))
			{
				m_nextChickenEggRequest = Time.unscaledTime + 1f;
				ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_ChickenEgg", Array.Empty<object>());
			}
		}

		private static void RPC_ChickenEgg(long sender)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && m_permsLoaded && m_instance.PeerQuarantined(sender))
			{
				m_instance.TryDropChickenEgg(sender);
			}
		}

		private void EggResult(long peer, string message)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(peer, "AdminManager_ChickenEggResult", new object[1] { message });
		}

		private static void RPC_ChickenEggResult(long sender, string message)
		{
			if (IsServerMessage(sender) && LocalQuarantined && !((Object)(object)Player.m_localPlayer == (Object)null) && !string.IsNullOrEmpty(message) && message.Length <= 256)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
		}

		private void TryDropChickenEgg(long sender)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			object obj;
			if (peer == null)
			{
				obj = null;
			}
			else
			{
				ISocket socket = peer.m_socket;
				obj = ((socket != null) ? socket.GetHostName() : null);
			}
			string text = (string)obj;
			if (!ValidQuarantineAccount(text) || !m_quarantineAccounts.Contains(text) || (m_chickenEggAttempts.TryGetValue(text, out var value) && Time.unscaledTime < value))
			{
				return;
			}
			m_chickenEggAttempts[text] = Time.unscaledTime + 1f;
			if (!m_chickenEggStorageReady)
			{
				EggResult(sender, "Egg drops are unavailable; the server could not load their quota.");
				return;
			}
			ZDO val = ((!((ZDOID)(ref peer.m_characterID)).IsNone() && ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(peer.m_characterID) : null);
			GameObject val2 = ((val != null && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null);
			if (val == null || (Object)(object)val2 == (Object)null || (Object)(object)val2.GetComponent<Player>() == (Object)null || val.GetOwner() != sender)
			{
				return;
			}
			Player val3 = FindInventoryCharacter(peer.m_characterID);
			if ((Object)(object)val3 != (Object)null && ((Character)val3).IsDead())
			{
				return;
			}
			Vector3 val4 = val.GetPosition() - val.GetRotation() * Vector3.forward * 0.65f + Vector3.up * 0.5f;
			if (!FinitePosition(val4))
			{
				return;
			}
			GameObject val5 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("ChickenEgg") : null);
			ItemDrop val6 = (((Object)(object)val5 != (Object)null) ? val5.GetComponent<ItemDrop>() : null);
			if (val6?.m_itemData == null)
			{
				EggResult(sender, "Chicken eggs are unavailable in this session.");
				return;
			}
			long ticks = DateTime.UtcNow.Ticks;
			if (!m_chickenEggTimes.TryGetValue(text, out var value2))
			{
				if (m_chickenEggTimes.Count >= 4096)
				{
					string[] array = m_chickenEggTimes.Keys.ToArray();
					foreach (string key in array)
					{
						PruneChickenEggTimes(m_chickenEggTimes[key], ticks);
						if (m_chickenEggTimes[key].Count == 0)
						{
							m_chickenEggTimes.Remove(key);
						}
					}
					if (m_chickenEggTimes.Count >= 4096)
					{
						return;
					}
				}
				value2 = new List<long>();
				m_chickenEggTimes.Add(text, value2);
			}
			if (!ReserveChickenEgg(value2, ticks))
			{
				int num = (int)Math.Min(600.0, Math.Max(1.0, Math.Ceiling((double)(value2.Min() + ChickenEggWindow - ticks) / 10000000.0)));
				EggResult(sender, "Egg limit reached (3 per 10 minutes). Next egg in " + num / 60 + "m " + num % 60 + "s.");
				return;
			}
			ItemDrop val7 = null;
			try
			{
				SaveEggQuotas(ticks);
				ItemData obj2 = val6.m_itemData.Clone();
				obj2.m_dropPrefab = val5;
				obj2.m_stack = 1;
				obj2.m_equipped = false;
				val7 = ItemDrop.DropItem(obj2, 1, val4, Quaternion.identity);
				ZNetView val8 = (((Object)(object)val7 != (Object)null) ? ((Component)val7).GetComponent<ZNetView>() : null);
				if ((Object)(object)val8 == (Object)null || !val8.IsValid())
				{
					throw new InvalidOperationException("Egg pickup was not created.");
				}
				EggResult(sender, "Cluck! Egg laid (" + value2.Count + "/3 in the last 10 minutes).");
			}
			catch (Exception ex)
			{
				if ((Object)(object)val7 != (Object)null)
				{
					ZNetView component = ((Component)val7).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid())
					{
						ZNetScene.instance.Destroy(((Component)val7).gameObject);
					}
					else
					{
						Object.Destroy((Object)(object)((Component)val7).gameObject);
					}
				}
				value2.RemoveAt(value2.Count - 1);
				try
				{
					SaveEggQuotas(ticks);
				}
				catch (Exception ex2)
				{
					Log.LogWarning((object)("Egg quota rollback could not be saved: " + ex2.Message));
				}
				Log.LogWarning((object)("Chicken egg drop failed: " + ex.Message));
				EggResult(sender, "Could not lay an egg; try again later.");
			}
		}

		private void ResetChickenEggs()
		{
			m_chickenEggTimes.Clear();
			m_chickenEggAttempts.Clear();
			m_chickenEggStorageReady = false;
			m_nextChickenEggRequest = 0f;
		}

		private static bool ValidBuildFingerprint(string hash)
		{
			if (hash != null && hash.Length == 64)
			{
				return hash.All((char c) => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
			}
			return false;
		}

		private static bool MatchingClientBuild(string expectedVersion, string expectedHash, string version, string hash)
		{
			if (!string.IsNullOrEmpty(expectedVersion) && string.Equals(expectedVersion, version, StringComparison.Ordinal) && ValidBuildFingerprint(expectedHash) && ValidBuildFingerprint(hash))
			{
				return string.Equals(expectedHash, hash, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private static bool ClientAdmissionAllowed(bool required, bool verified, bool rejected)
		{
			if (!rejected)
			{
				return !required || verified;
			}
			return false;
		}

		private static bool ValidHandshakeNonce(string nonce)
		{
			Guid result;
			if (nonce != null && nonce.Length == 32)
			{
				return Guid.TryParseExact(nonce, "N", out result);
			}
			return false;
		}

		private static bool MatchesHandshakeNonce(string expected, string received)
		{
			if (ValidHandshakeNonce(expected) && ValidHandshakeNonce(received))
			{
				return string.Equals(expected, received, StringComparison.Ordinal);
			}
			return false;
		}

		private void InitializeClientCompatibility()
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_017f: Expected O, but got Unknown
			//IL_01a2: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_01d5: Expected O, but got Unknown
			m_requireMatchingClient = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "RequireMatchingClient", true, "Server setting: require Admin Manager with the same version and DLL build before admitting clients. False allows missing/mismatched clients; remote features may be unavailable. Restart the host/server after changing this setting.");
			try
			{
				string location = typeof(Plugin).Assembly.Location;
				if (string.IsNullOrEmpty(location))
				{
					location = ((BaseUnityPlugin)this).Info.Location;
				}
				using FileStream inputStream = File.OpenRead(location);
				using SHA256 sHA = SHA256.Create();
				m_buildFingerprint = BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Cannot fingerprint Admin Manager; required-mode connections will be rejected: " + ex.Message));
			}
			m_nativePeerInfo = AccessTools.Method(typeof(ZNet), "RPC_PeerInfo", new Type[2]
			{
				typeof(ZRpc),
				typeof(ZPackage)
			}, (Type[])null);
			if (m_nativePeerInfo == null)
			{
				throw new MissingMethodException("ZNet.RPC_PeerInfo");
			}
			m_harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "OnNewConnection", new Type[1] { typeof(ZNetPeer) }, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientConnectionPrefix", (Type[])null, (Type[])null))
			{
				priority = 800
			}, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientConnectionPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			m_harmony.Patch((MethodBase)m_nativePeerInfo, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientPeerInfoPrefix", (Type[])null, (Type[])null))
			{
				priority = 800
			}, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "ClientPeerInfoPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void ClientConnectionPrefix(ZNet __instance, ZNetPeer peer)
		{
			if (!((Object)(object)m_instance == (Object)null) && peer?.m_rpc != null)
			{
				ClientGate value = new ClientGate
				{
					Net = __instance,
					Peer = peer,
					Nonce = Guid.NewGuid().ToString("N"),
					Required = (__instance.IsServer() && m_instance.m_requireMatchingClient.Value)
				};
				m_instance.m_clientGates[peer.m_rpc] = value;
				if (!__instance.IsServer())
				{
					m_instance.m_connectionNotice = "";
				}
				peer.m_rpc.Register<ZPackage>("AdminManager_ClientChallenge", (Action<ZRpc, ZPackage>)RPC_ClientChallenge);
				peer.m_rpc.Register<ZPackage>("AdminManager_ClientHello", (Action<ZRpc, ZPackage>)RPC_ClientHello);
				peer.m_rpc.Register<string>("AdminManager_ClientRejected", (Action<ZRpc, string>)RPC_ClientRejected);
			}
		}

		private static void ClientConnectionPostfix(ZNet __instance, ZNetPeer peer)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!((Object)(object)m_instance == (Object)null) && __instance.IsServer() && peer?.m_rpc != null && m_instance.m_clientGates.TryGetValue(peer.m_rpc, out var value))
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(value.Nonce);
				val.Write("1.0.2");
				val.Write(m_instance.m_buildFingerprint);
				val.Write(value.Required);
				peer.m_rpc.Invoke("AdminManager_ClientChallenge", new object[1] { val });
			}
		}

		private static void RPC_ClientChallenge(ZRpc rpc, ZPackage package)
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			if ((Object)(object)m_instance == (Object)null || !m_instance.m_clientGates.TryGetValue(rpc, out var value) || (Object)(object)value.Net != (Object)(object)ZNet.instance || value.Net.IsServer() || value.Rejected || package == null || package.Size() > 512)
			{
				return;
			}
			try
			{
				int num = package.ReadInt();
				string text = package.ReadString();
				string text2 = package.ReadString();
				string text3 = package.ReadString();
				bool flag = package.ReadBool();
				if (package.GetPos() == package.Size() && ValidHandshakeNonce(text) && text2.Length <= 32 && ValidBuildFingerprint(text3))
				{
					if (flag && (num != 1 || !MatchingClientBuild(text2, text3, "1.0.2", m_instance.m_buildFingerprint)))
					{
						m_instance.m_connectionNotice = "This server requires Admin Manager " + text2 + " with the exact same build. Install the server owner's package and restart Valheim.";
					}
					ZPackage val = new ZPackage();
					val.Write(1);
					val.Write(text);
					val.Write("1.0.2");
					val.Write(m_instance.m_buildFingerprint);
					rpc.Invoke("AdminManager_ClientHello", new object[1] { val });
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Invalid Admin Manager server handshake: " + ex.Message));
			}
		}

		private static void RPC_ClientHello(ZRpc rpc, ZPackage package)
		{
			if ((Object)(object)m_instance == (Object)null || !m_instance.m_clientGates.TryGetValue(rpc, out var value) || (Object)(object)value.Net != (Object)(object)ZNet.instance || !value.Net.IsServer() || value.Rejected || value.Verified || package == null || package.Size() > 512)
			{
				return;
			}
			try
			{
				int num = package.ReadInt();
				string received = package.ReadString();
				string version = package.ReadString();
				string hash = package.ReadString();
				if (package.GetPos() != package.Size() || !MatchesHandshakeNonce(value.Nonce, received))
				{
					return;
				}
				bool flag = num == 1 && MatchingClientBuild("1.0.2", m_instance.m_buildFingerprint, version, hash);
				if (!flag && value.Required)
				{
					m_instance.RejectClient(value, "Incompatible Admin Manager build. Install Admin Manager 1.0.2 from the server owner and restart Valheim.");
					return;
				}
				value.Verified = flag;
				if (!flag)
				{
					Log.LogWarning((object)"Optional Admin Manager client build differs; remote tools may be unavailable.");
				}
				if (ClientAdmissionAllowed(value.Required, value.Verified, value.Rejected) && value.Pending != null)
				{
					ZPackage pending = value.Pending;
					value.Pending = null;
					m_instance.m_nativePeerInfo.Invoke(value.Net, new object[2] { rpc, pending });
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Invalid Admin Manager client handshake: " + ex.Message));
				if (value.Required)
				{
					m_instance.RejectClient(value, "Invalid Admin Manager handshake. Install the server owner's Admin Manager 1.0.2 build and restart Valheim.");
				}
			}
		}

		private static bool ClientPeerInfoPrefix(ZNet __instance, ZRpc rpc, ZPackage pkg)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			if ((Object)(object)m_instance == (Object)null || !__instance.IsServer())
			{
				return true;
			}
			if (!m_instance.m_clientGates.TryGetValue(rpc, out var value))
			{
				return !m_instance.m_requireMatchingClient.Value;
			}
			if (value.Rejected || value.Admitted)
			{
				return false;
			}
			if (ClientAdmissionAllowed(value.Required, value.Verified, value.Rejected))
			{
				return true;
			}
			if (value.Pending == null)
			{
				if (pkg == null || pkg.Size() > 65536)
				{
					m_instance.RejectClient(value, "Invalid connection information.");
					return false;
				}
				int pos = pkg.GetPos();
				value.Pending = new ZPackage(pkg.GetArray());
				value.Pending.SetPos(pos);
				value.Deadline = Time.unscaledTime + 10f;
			}
			return false;
		}

		private static void ClientPeerInfoPostfix(ZNet __instance, ZRpc rpc)
		{
			if ((Object)(object)m_instance != (Object)null && __instance.IsServer() && m_instance.m_clientGates.TryGetValue(rpc, out var value) && value.Peer.IsReady())
			{
				value.Admitted = true;
			}
		}

		private void RejectClient(ClientGate gate, string reason)
		{
			if (!gate.Rejected)
			{
				gate.Rejected = true;
				gate.Pending = null;
				gate.DisconnectAt = Time.unscaledTime + 1f;
				ManualLogSource log = Log;
				ISocket socket = gate.Peer.m_socket;
				log.LogWarning((object)("Admin Manager connection rejected (" + ((socket != null) ? socket.GetHostName() : null) + "): " + reason));
				gate.Peer.m_rpc.Invoke("AdminManager_ClientRejected", new object[1] { reason });
				gate.Peer.m_rpc.Invoke("Error", new object[1] { 3 });
			}
		}

		private static void RPC_ClientRejected(ZRpc rpc, string reason)
		{
			if (!((Object)(object)m_instance == (Object)null) && m_instance.m_clientGates.TryGetValue(rpc, out var value) && !((Object)(object)value.Net != (Object)(object)ZNet.instance) && !value.Net.IsServer() && !string.IsNullOrEmpty(reason) && reason.Length <= 512)
			{
				value.Rejected = true;
				m_instance.m_connectionNotice = reason;
				Log.LogWarning((object)("Server rejected Admin Manager connection: " + reason));
				ZNet.SetExternalError((ConnectionStatus)3);
			}
		}

		private void UpdateConnectionChecks()
		{
			KeyValuePair<ZRpc, ClientGate>[] array = m_clientGates.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<ZRpc, ClientGate> keyValuePair = array[i];
				ClientGate value = keyValuePair.Value;
				if ((Object)(object)value.Net == (Object)null || (Object)(object)value.Net != (Object)(object)ZNet.instance || !value.Net.GetPeers().Contains(value.Peer))
				{
					m_clientGates.Remove(keyValuePair.Key);
				}
				else if (value.Net.IsServer())
				{
					if (!value.Rejected && value.Required && !value.Verified && value.Pending != null && Time.unscaledTime >= value.Deadline)
					{
						RejectClient(value, "Admin Manager 1.0.2 is required. Install the server owner's matching build and restart Valheim.");
					}
					if (value.Rejected && Time.unscaledTime >= value.DisconnectAt)
					{
						value.Net.Disconnect(value.Peer);
						m_clientGates.Remove(keyValuePair.Key);
					}
				}
			}
		}

		private void DrawConnectionNotice()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(m_connectionNotice))
			{
				int depth = GUI.depth;
				GUI.depth = -2000;
				float num = Math.Min(560f, (float)Screen.width - 24f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 24f, num, 130f);
				GUI.Box(val, "");
				GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 8f, num - 24f, 26f), "Admin Manager — connection requirement");
				GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 36f, num - 24f, 54f), m_connectionNotice, new GUIStyle(GUI.skin.label)
				{
					wordWrap = true,
					richText = false
				});
				if (GUI.Button(new Rect(((Rect)(ref val)).xMax - 112f, ((Rect)(ref val)).yMax - 32f, 100f, 24f), "Dismiss"))
				{
					m_connectionNotice = "";
				}
				GUI.depth = depth;
			}
		}

		private void RegisterFeatures()
		{
			RegisterInventory();
			RegisterWorldSettings();
			RegisterResources();
			RegisterInvisibility();
			RegisterFreeze();
			RegisterQuarantine();
			RegisterInventoryModeration();
			ZRoutedRpc instance = ZRoutedRpc.instance;
			instance.Register<string, bool>("AdminManager_Feedback", (Action<long, string, bool>)RPC_Feedback);
			instance.Register<string, float>("AdminManager_Area", (Action<long, string, float>)RPC_Area);
			instance.Register<long, bool>("AdminManager_Teleport", (Action<long, long, bool>)RPC_Teleport);
			instance.Register<int, Vector3, Quaternion>("AdminManager_TeleportApply", (Action<long, int, Vector3, Quaternion>)RPC_TeleportApply);
			instance.Register<int, bool>("AdminManager_TeleportResult", (Action<long, int, bool>)RPC_TeleportResult);
			instance.Register("AdminManager_GetRoster", (Action<long>)RPC_GetRoster);
			instance.Register<string>("AdminManager_Roster", (Action<long, string>)RPC_Roster);
			instance.Register<long>("AdminManager_OfflineBan", (Action<long, long>)RPC_OfflineBan);
			instance.Register("AdminManager_SaveWorld", (Action<long>)RPC_SaveWorld);
		}

		private void ResetFeatures()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			m_previewPlayerInstanceId = 0;
			ResetModeration();
			ResetWorldSettings();
			ResetQuarantine();
			ResetInvisibility();
			ResetResources();
			m_inventoryRequests.Clear();
			m_inventoryCooldowns.Clear();
			m_inventoryTarget = 0L;
			m_inventoryCharacter = ZDOID.None;
			m_inventoryPreview = null;
			m_knownPlayers.Clear();
			m_pendingTeleports.Clear();
			m_offlineSelection = 0L;
			m_teleportSelection = 0L;
			m_nextRosterScan = (m_nextRosterSave = (m_nextRosterRequest = (m_nextWorldSave = 0f)));
			m_feedback = "";
		}

		private static void Feedback(string message, bool error = false)
		{
			if (!((Object)(object)m_instance == (Object)null))
			{
				m_instance.m_feedback = message;
				m_instance.m_feedbackError = error;
				m_instance.m_feedbackUntil = Time.unscaledTime + 12f;
			}
		}

		private static void Reply(long peer, string message, bool error = false)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				if (peer == ServerPeerId())
				{
					Feedback(message, error);
				}
				else if (ZNet.instance.GetPeer(peer) != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(peer, "AdminManager_Feedback", new object[2] { message, error });
				}
			}
		}

		private static void RPC_Feedback(long sender, string message, bool error)
		{
			if (IsServerMessage(sender))
			{
				Feedback(message, error);
			}
		}

		private void DrawFeedback()
		{
			//IL_0024: 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_0038: Expected O, but got Unknown
			//IL_006b: 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)
			string obj = ((Time.unscaledTime > m_feedbackUntil) ? "" : m_feedback);
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				wordWrap = true,
				richText = false
			};
			val.normal.textColor = (m_feedbackError ? new Color(1f, 0.55f, 0.4f) : new Color(0.65f, 1f, 0.65f));
			GUILayout.Label(obj, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
		}

		private void SendFeature(string rpc, params object[] args)
		{
			if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null)
			{
				Feedback("Load a world before using this action.", error: true);
				return;
			}
			Feedback("Waiting for the server...");
			if (!ZNet.instance.IsServer())
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), rpc, args);
				return;
			}
			long sender = ServerPeerId();
			switch (rpc)
			{
			case "AdminManager_Area":
				RPC_Area(sender, (string)args[0], (float)args[1]);
				break;
			case "AdminManager_Teleport":
				RPC_Teleport(sender, (long)args[0], (bool)args[1]);
				break;
			case "AdminManager_SaveWorld":
				RPC_SaveWorld(sender);
				break;
			case "AdminManager_OfflineBan":
				RPC_OfflineBan(sender, (long)args[0]);
				break;
			}
		}

		private static bool ValidRadius(float radius)
		{
			if (!float.IsNaN(radius) && !float.IsInfinity(radius) && radius >= 5f)
			{
				return radius <= 100f;
			}
			return false;
		}

		private static bool IsAreaCommand(string command)
		{
			switch (command)
			{
			default:
				return command == "killenemies";
			case "removedrops":
			case "tame":
			case "killall":
				return true;
			}
		}

		private static bool TryPlayerLocation(long pid, out Vector3 position, out Quaternion rotation)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			if (pid == 0L)
			{
				return false;
			}
			Player val = FindPlayerById(pid);
			if ((Object)(object)val != (Object)null)
			{
				position = ((Component)val).transform.position;
				rotation = ((Component)val).transform.rotation;
				return true;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (PeerPlayerId(peer) == pid && !((ZDOID)(ref peer.m_characterID)).IsNone())
				{
					ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
					if (zDO == null)
					{
						return false;
					}
					position = zDO.GetPosition();
					rotation = zDO.GetRotation();
					return true;
				}
			}
			return false;
		}

		private static void RPC_Area(long sender, string command, float radius)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			if (!IsAreaCommand(command) || !ValidRadius(radius))
			{
				Reply(sender, "Invalid area action or radius.", error: true);
				return;
			}
			long pid = PlayerIdOfPeer(sender);
			if (!IsAdminSender(sender) && !HasPerm(pid, command))
			{
				Reply(sender, "Permission denied.", error: true);
				return;
			}
			if (!TryPlayerLocation(pid, out var position, out var _))
			{
				Reply(sender, "Your character is not ready.", error: true);
				return;
			}
			try
			{
				int num = 0;
				if (command == "tame")
				{
					Tameable.TameAllInArea(position, radius);
					Reply(sender, "Tame applied to eligible loaded creatures within " + radius.ToString("0") + " m.");
					return;
				}
				float num2 = radius * radius;
				Vector3 val2;
				if (command == "removedrops")
				{
					ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
					foreach (ItemDrop val in array)
					{
						if ((Object)(object)val == (Object)null)
						{
							continue;
						}
						val2 = ((Component)val).transform.position - position;
						if (((Vector3)(ref val2)).sqrMagnitude > num2)
						{
							continue;
						}
						ZNetView component = ((Component)val).GetComponent<ZNetView>();
						if (!((Object)(object)component == (Object)null) && component.IsValid())
						{
							component.ClaimOwnership();
							if (component.IsOwner())
							{
								ZNetScene.instance.Destroy(((Component)val).gameObject);
								num++;
							}
						}
					}
					Reply(sender, "Removed " + num + " loaded item stacks within " + radius.ToString("0") + " m.");
					return;
				}
				foreach (Character item in new List<Character>(Character.GetAllCharacters()))
				{
					if (!((Object)(object)item == (Object)null) && !item.IsPlayer() && !((Object)(object)((Component)item).GetComponent<Piece>() != (Object)null) && (!(command == "killenemies") || !item.IsTamed()))
					{
						val2 = ((Component)item).transform.position - position;
						if (!(((Vector3)(ref val2)).sqrMagnitude > num2))
						{
							item.Damage(new HitData(1E+10f));
							num++;
						}
					}
				}
				Reply(sender, "Damage sent to " + num + " loaded creatures within " + radius.ToString("0") + " m.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Area action failed: " + ex));
				Reply(sender, "Area action failed; check the server log.", error: true);
			}
		}

		private void DrawWorldTools(bool admin)
		{
			if (admin)
			{
				if (GUILayout.Button("Save World", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
				{
					SendFeature("AdminManager_SaveWorld");
				}
				GUILayout.Space(10f);
			}
		}

		private void DrawAreaTools()
		{
			if (CanUse("removedrops") || CanUse("tame") || CanUse("killall") || CanUse("killenemies"))
			{
				GUILayout.Space(14f);
				GUILayout.Label("Area actions", m_centerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Action radius: " + m_actionRadius.ToString("0") + " m", m_centerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				m_actionRadius = Mathf.Round(GUILayout.HorizontalSlider(m_actionRadius, 5f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) }));
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
				GUILayout.Label("Applies to Remove Drops, Tame, Kill All and Kill Enemies in loaded areas.", m_centerLabel, Array.Empty<GUILayoutOption>());
			}
		}

		private static void RPC_SaveWorld(long sender)
		{
			if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null)
			{
				return;
			}
			if (!IsAdminSender(sender))
			{
				Reply(sender, "Permission denied: only admins can save the world.", error: true);
				return;
			}
			if (Time.unscaledTime < m_instance.m_nextWorldSave)
			{
				Reply(sender, "A save was recently requested; wait a few seconds.", error: true);
				return;
			}
			try
			{
				if (ZNet.instance.HardSaveBlock())
				{
					Reply(sender, "Valheim is delaying another save; try again later.", error: true);
					return;
				}
				bool started = false;
				Action action = delegate
				{
					started = true;
				};
				ZNet.WorldSaveStarted = (Action)Delegate.Combine(ZNet.WorldSaveStarted, action);
				try
				{
					ZNet.instance.SaveWorldAndPlayerProfiles();
				}
				finally
				{
					ZNet.WorldSaveStarted = (Action)Delegate.Remove(ZNet.WorldSaveStarted, action);
				}
				m_instance.m_nextWorldSave = Time.unscaledTime + 15f;
				Reply(sender, started ? "World save started. Valheim will report completion." : "Valheim did not start the save; check its messages and server log.", !started);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Save World failed: " + ex));
				Reply(sender, "World save request failed.", error: true);
			}
		}

		private void DrawTeleportTools(long pid, float available = 0f)
		{
			float available2 = ((available > 0f) ? available : Math.Max(200f, ((Rect)(ref m_window)).width - 100f));
			bool enabled = pid != 0L && pid != (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			DrawActionGroup("Teleport", available2, new PlayerPanelAction("Teleport to Player", delegate
			{
				SendFeature("AdminManager_Teleport", pid, false);
			}, enabled, active: false, "teleport"), new PlayerPanelAction("Bring Player", delegate
			{
				SendFeature("AdminManager_Teleport", pid, true);
			}, enabled, active: false, "bring"));
		}

		private void DrawOnlineTeleportSelector()
		{
			List<KnownPlayer> list = new List<KnownPlayer>();
			foreach (KnownPlayer value in m_knownPlayers.Values)
			{
				if (IsOnline(value.Id) && (Object)(object)FindPlayerById(value.Id) == (Object)null)
				{
					list.Add(value);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			GUILayout.Space(10f);
			GUILayout.Label("Other online players (outside character view)", m_centerLabel, Array.Empty<GUILayoutOption>());
			list.Sort((KnownPlayer a, KnownPlayer b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			int num = 0;
			foreach (KnownPlayer item in list)
			{
				if (IsOnline(item.Id) && (!((Object)(object)Player.m_localPlayer != (Object)null) || item.Id != Player.m_localPlayer.GetPlayerID()))
				{
					num++;
					if (GUILayout.Button(item.Name, (item.Id == m_teleportSelection) ? m_tabActive : m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
					{
						m_teleportSelection = item.Id;
						RequestInventory(item.Id);
					}
				}
			}
			if (num == 0)
			{
				GUILayout.Label("No other online players.", m_centerLabel, Array.Empty<GUILayoutOption>());
			}
			if (m_teleportSelection != 0L && IsOnline(m_teleportSelection))
			{
				DrawTeleportTools(m_teleportSelection);
				DrawDistantFreezeTools(m_teleportSelection);
				DrawInventoryPreview(m_teleportSelection);
			}
		}

		private static void RPC_Teleport(long sender, long target, bool bring)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00d9: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			if (DenyQuarantined(sender))
			{
				return;
			}
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null)
				{
					return;
				}
				if (!IsAdminSender(sender))
				{
					Reply(sender, "Permission denied: only admins can teleport players.", error: true);
					return;
				}
				long num = PlayerIdOfPeer(sender);
				if (target == num || target == 0L || num == 0L)
				{
					Reply(sender, "Select another online player.", error: true);
					return;
				}
				if (!TryPlayerLocation(num, out var position, out var rotation) || !TryPlayerLocation(target, out var position2, out var rotation2))
				{
					Reply(sender, "Both players must be online with their characters loaded.", error: true);
					return;
				}
				if (m_instance.ServerProfileFrozen(num) || m_instance.ServerProfileFrozen(target))
				{
					Reply(sender, "Unfreeze the player before teleporting.", error: true);
					return;
				}
				long num2 = (bring ? target : num);
				Vector3 val = (bring ? position : position2);
				Quaternion val2 = (bring ? rotation : rotation2);
				val += val2 * new Vector3(2f, 1f, 0f);
				string text = (bring ? "Bring player" : "Teleport to player");
				if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == num2)
				{
					bool flag = ((Character)Player.m_localPlayer).TeleportTo(val, val2, true);
					Reply(sender, flag ? (text + " started.") : "Teleport unavailable while already teleporting or attached.", !flag);
					return;
				}
				long num3 = 0L;
				foreach (ZNetPeer peer in ZNet.instance.GetPeers())
				{
					if (PeerPlayerId(peer) == num2)
					{
						num3 = peer.m_uid;
						break;
					}
				}
				if (num3 == 0L)
				{
					Reply(sender, "The player disconnected.", error: true);
					return;
				}
				foreach (PendingTeleport value in m_instance.m_pendingTeleports.Values)
				{
					if (value.Peer == num3)
					{
						Reply(sender, "A teleport is already pending for this player.", error: true);
						return;
					}
				}
				int num4 = ++m_instance.m_nextTeleport;
				m_instance.m_pendingTeleports[num4] = new PendingTeleport
				{
					Requester = sender,
					Peer = num3,
					Description = text,
					Expires = Time.unscaledTime + 20f
				};
				ZRoutedRpc.instance.InvokeRoutedRPC(num3, "AdminManager_TeleportApply", new object[3] { num4, val, val2 });
				Reply(sender, text + " sent; waiting for the player's client.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Teleport request failed: " + ex));
				Reply(sender, "Teleport failed; check the server log.", error: true);
			}
		}

		private static void RPC_TeleportApply(long sender, int id, Vector3 pos, Quaternion rot)
		{
			//IL_001d: 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)
			if (IsServerMessage(sender))
			{
				bool flag = false;
				try
				{
					flag = (Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).TeleportTo(pos, rot, true);
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Teleport failed: " + ex));
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_TeleportResult", new object[2] { id, flag });
				Feedback(flag ? "Admin teleport started." : "Admin teleport could not start.", !flag);
			}
		}

		private static void RPC_TeleportResult(long sender, int id, bool accepted)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && m_instance.m_pendingTeleports.TryGetValue(id, out var value) && value.Peer == sender)
			{
				m_instance.m_pendingTeleports.Remove(id);
				Reply(value.Requester, accepted ? (value.Description + " started.") : "The player's client could not start the teleport.", !accepted);
			}
		}

		private void UpdateFeatures(bool server)
		{
			UpdateResources(server);
			UpdateWorldSettings(server);
			UpdateQuarantine(server);
			UpdateInvisibility(server);
			UpdateModeration();
			if (server)
			{
				if (!m_permsLoaded)
				{
					return;
				}
				UpdateInventoryRequests();
				if (Time.unscaledTime >= m_nextRosterScan)
				{
					m_nextRosterScan = Time.unscaledTime + 5f;
					RememberOnlinePlayers();
				}
				if (Time.unscaledTime >= m_nextRosterSave)
				{
					m_nextRosterSave = Time.unscaledTime + 60f;
					SaveRoster();
				}
				{
					foreach (int item in new List<int>(m_pendingTeleports.Keys))
					{
						PendingTeleport pendingTeleport = m_pendingTeleports[item];
						if (!(Time.unscaledTime < pendingTeleport.Expires))
						{
							m_pendingTeleports.Remove(item);
							Reply(pendingTeleport.Requester, "No teleport response; check that the player has the same mod version.", error: true);
						}
					}
					return;
				}
			}
			if (m_show && IsLocalAdmin() && Time.unscaledTime >= m_nextRosterRequest)
			{
				m_nextRosterRequest = Time.unscaledTime + 10f;
				ZRoutedRpc.instance.InvokeRoutedRPC(ServerPeerId(), "AdminManager_GetRoster", Array.Empty<object>());
			}
		}

		private void Remember(long id, string name, string host)
		{
			if (id != 0L)
			{
				bool flag = !m_knownPlayers.TryGetValue(id, out var value);
				if (value == null)
				{
					value = new KnownPlayer
					{
						Id = id
					};
					m_knownPlayers[id] = value;
				}
				if (!string.IsNullOrWhiteSpace(name))
				{
					flag |= value.Name != name;
					value.Name = name;
				}
				else if (string.IsNullOrWhiteSpace(value.Name))
				{
					value.Name = "Player " + id;
				}
				flag |= !string.IsNullOrEmpty(host) && value.Host != host;
				if (!string.IsNullOrEmpty(host))
				{
					value.Host = host;
				}
				value.LastSeen = DateTime.UtcNow.Ticks;
				if (flag)
				{
					SaveRoster();
				}
			}
		}

		private void RememberOnlinePlayers()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Remember(Player.m_localPlayer.GetPlayerID(), Player.m_localPlayer.GetPlayerName(), "");
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				Remember(PeerPlayerId(peer), peer.m_playerName, (peer.m_socket != null) ? peer.m_socket.GetHostName() : "");
			}
		}

		private static string Encode(string value)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? ""));
		}

		private static string Decode(string value)
		{
			return Encoding.UTF8.GetString(Convert.FromBase64String(value));
		}

		private string SerializeRoster(bool privateData)
		{
			List<string> list = new List<string>();
			foreach (KnownPlayer value in m_knownPlayers.Values)
			{
				list.Add(value.Id.ToString(CultureInfo.InvariantCulture) + "|" + Encode(value.Name) + "|" + Encode(privateData ? value.Host : "") + "|" + value.LastSeen.ToString(CultureInfo.InvariantCulture) + "|" + ((!privateData && IsOnline(value.Id)) ? "1" : "0"));
			}
			return string.Join("\n", list.ToArray());
		}

		private void ParseRoster(string data)
		{
			Dictionary<long, KnownPlayer> dictionary = new Dictionary<long, KnownPlayer>();
			string[] array = data.Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { '|' });
				if ((array2.Length != 4 && array2.Length != 5) || !long.TryParse(array2[0], out var result) || result == 0L || !long.TryParse(array2[3], out var result2))
				{
					continue;
				}
				long num = result2;
				DateTime minValue = DateTime.MinValue;
				if (num < minValue.Ticks)
				{
					continue;
				}
				long num2 = result2;
				minValue = DateTime.MaxValue;
				if (num2 <= minValue.Ticks)
				{
					try
					{
						dictionary[result] = new KnownPlayer
						{
							Id = result,
							Name = Decode(array2[1]),
							Host = Decode(array2[2]),
							LastSeen = result2,
							Online = (array2.Length == 5 && array2[4] == "1")
						};
					}
					catch (FormatException)
					{
					}
				}
			}
			m_knownPlayers.Clear();
			foreach (KeyValuePair<long, KnownPlayer> item in dictionary)
			{
				m_knownPlayers[item.Key] = item.Value;
			}
		}

		private void LoadRoster()
		{
			m_knownPlayers.Clear();
			try
			{
				string text = DataPath("players");
				if (text != null && File.Exists(text))
				{
					ParseRoster(File.ReadAllText(text));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Load player history failed: " + ex));
			}
			HashSet<long> hashSet = new HashSet<long>(m_permPlayers.Keys);
			hashSet.UnionWith(m_admins);
			foreach (long item in hashSet)
			{
				if (item != 0L && !m_knownPlayers.ContainsKey(item))
				{
					m_knownPlayers[item] = new KnownPlayer
					{
						Id = item,
						Name = "Player " + item,
						Host = "",
						LastSeen = 0L
					};
				}
			}
		}

		private void SaveRoster()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !m_permsLoaded)
			{
				return;
			}
			try
			{
				string text = DataPath("players");
				if (text != null)
				{
					string text2 = text + ".tmp";
					File.WriteAllText(text2, SerializeRoster(privateData: true));
					if (File.Exists(text))
					{
						File.Replace(text2, text, text + ".bak");
					}
					else
					{
						File.Move(text2, text);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Save player history failed: " + ex));
			}
		}

		private static void RPC_GetRoster(long sender)
		{
			if (!DenyQuarantined(sender) && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)m_instance == (Object)null) && IsAdminSender(sender))
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "AdminManager_Roster", new object[1] { m_instance.SerializeRoster(privateData: false) });
			}
		}

		private static void RPC_Roster(long sender, string data)
		{
			if (IsServerMessage(sender) && (Object)(object)m_instance != (Object)null)
			{
				m_instance.ParseRoster(data);
			}
		}

		private bool IsOnline(long id)
		{
			if ((Object)(object)FindPlayerById(id) != (Object)null)
			{
				return true;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (!ZNet.instance.IsServer())
			{
				if (m_knownPlayers.TryGetValue(id, out var value))
				{
					return value.Online;
				}
				return false;
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (PeerPlayerId(peer) == id)
				{
					return true;
				}
			}
			return false;
		}

		private void DrawOfflineTab()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Previously connected players", m_centerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Manage saved permissions and admin access while players are offline.", m_centerLabel, Array.Empty<GUILayoutOption>());
			m_rosterSearch = GUILayout.TextField(m_rosterSearch, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Math.Min(520f, ((Rect)(ref m_window)).width - 64f)) });
			m_rosterScroll = GUILayout.BeginScrollView(m_rosterScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(160f) });
			List<KnownPlayer> list = new List<KnownPlayer>(m_knownPlayers.Values);
			list.Sort((KnownPlayer a, KnownPlayer b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			int num = 0;
			foreach (KnownPlayer item in list)
			{
				if (!IsOnline(item.Id) && (string.IsNullOrEmpty(m_rosterSearch) || (item.Name ?? "").IndexOf(m_rosterSearch, StringComparison.OrdinalIgnoreCase) >= 0 || item.Id.ToString().Contains(m_rosterSearch)))
				{
					num++;
					if (GUILayout.Button(item.Name, (item.Id == m_offlineSelection) ? m_tabActive : m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
					{
						m_offlineSelection = item.Id;
					}
				}
			}
			if (num == 0)
			{
				GUILayout.Label("No offline players recorded yet.", Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(12f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Math.Min(520f, ((Rect)(ref m_window)).width - 64f)) });
			if (m_knownPlayers.TryGetValue(m_offlineSelection, out var value) && !IsOnline(value.Id))
			{
				GUILayout.Label(value.Name, m_centerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Player ID: " + value.Id, m_centerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Inventory unavailable while offline.", m_centerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Last seen: " + ((value.LastSeen == 0L) ? "not recorded yet" : new DateTime(value.LastSeen, DateTimeKind.Utc).ToLocalTime().ToString("g")), m_centerLabel, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(IsModAdmin(value.Id) ? "Remove mod Admin" : "Grant mod Admin", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					ToggleAdmin(value.Id);
				}
				DrawQuarantineProfileTools(value.Id);
				if (GUILayout.Button("Ban this player", m_buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					SendFeature("AdminManager_OfflineBan", value.Id);
				}
			}
			else
			{
				GUILayout.Label("Select an offline player.", m_centerLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			if (m_knownPlayers.TryGetValue(m_offlineSelection, out value) && !IsOnline(value.Id))
			{
				DrawPermGrid(value.Id);
			}
		}

		private static void RPC_OfflineBan(long sender, long id)
		{
			if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null)
			{
				return;
			}
			if (!IsAdminSender(sender))
			{
				Reply(sender, "Permission denied.", error: true);
				return;
			}
			if (id == HostPlayerId() || !m_instance.m_knownPlayers.TryGetValue(id, out var value) || string.IsNullOrEmpty(value.Host))
			{
				Reply(sender, "No saved account address is available for this player.", error: true);
				return;
			}
			if (m_instance.IsOnline(id))
			{
				Reply(sender, "Player is online; use the Players tab.", error: true);
				return;
			}
			try
			{
				m_banNames[value.Host] = value.Name;
				ZNet.instance.Ban(value.Host);
				SaveBanNames();
				SendBansTo(sender);
				Reply(sender, "Banned " + value.Name + " using their last recorded account.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Offline ban failed: " + ex));
				Reply(sender, "Ban failed; check the server log.", error: true);
			}
		}

		private void RegisterFreeze()
		{
			ZRoutedRpc.instance.Register<ZDOID, bool>("AdminManager_FreezeRequest", (Action<long, ZDOID, bool>)RPC_FreezeRequest);
			ZRoutedRpc.instance.Register<long, bool>("AdminManager_FreezePlayerRequest", (Action<long, long, bool>)RPC_FreezePlayerRequest);
			ZRoutedRpc.instance.Register<ZDOID, bool>("AdminManager_FreezeApply", (Action<long, ZDOID, bool>)RPC_FreezeApply);
			ZRoutedRpc.instance.Register<ZDOID, bool, bool>("AdminManager_FreezeResult", (Action<long, ZDOID, bool, bool>)RPC_FreezeResult);
		}

		private void ApplyFreezePatches()
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			PatchResource(typeof(Player), "FixedUpdate", "FreezeFixedPostfix", prefix: false);
			PatchResource(typeof(Player), "TakeInput", "FreezeInputPostfix", prefix: false);
			PatchResource(typeof(Character), "TakeInput", "FreezeCharacterInputPostfix", prefix: false);
			PatchResource(typeof(PlayerController), "TakeInput", "FreezeControllerInputPostfix", prefix: false);
			MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2]
			{
				typeof(Character),
				typeof(bool)
			}, (Type[])null);
			m_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "FreezeAttackPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool FrozenCharacter(Player player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player != (Object)null && (Object)(object)m_instance != (Object)null)
			{
				return m_instance.m_ownedFreezes.ContainsKey(((Character)player).GetZDOID());
			}
			return false;
		}

		private static void FreezeInputPostfix(Player __instance, ref bool __result)
		{
			if (FrozenCharacter(__instance))
			{
				__result = false;
			}
		}

		private static void FreezeCharacterInputPostfix(Character __instance, ref bool __result)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null && FrozenCharacter(val))
			{
				__result = false;
			}
		}

		private static void FreezeControllerInputPostfix(PlayerController __instance, bool look, ref bool __result)
		{
			if (!look && FrozenCharacter(((Component)__instance).GetComponent<Player>()))
			{
				__result = false;
			}
		}

		private static bool FreezeAttackPrefix(Humanoid __instance, ref bool __result)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null && FrozenCharacter(val))
			{
				__result = false;
				return false;
			}
			return true;
		}

		private static void FreezeFixedPostfix(Player __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_instance == (Object)null || !m_instance.m_ownedFreezes.TryGetValue(((Character)__instance).GetZDOID(), out var value))
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				m_instance.RemoveOwnedFreeze(((Character)__instance).GetZDOID());
				return;
			}
			if ((Object)(object)value.Body != (Object)null)
			{
				value.Body.constraints = (RigidbodyConstraints)126;
				if (!value.Body.isKinematic)
				{
					value.Body.linearVelocity = Vector3.zero;
					value.Body.angularVelocity = Vector3.zero;
				}
				value.Body.position = value.Position;
				value.Body.rotation = value.Rotation;
			}
			((Component)__instance).transform.SetPositionAndRotation(value.Position, value.Rotation);
		}

		private bool SetOwnedFreeze(ZDOID character, bool frozen)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!frozen)
			{
				RemoveOwnedFreeze(character);
				return true;
			}
			if (m_ownedFreezes.ContainsKey(character))
			{
				return true;
			}
			Player val = FindInventoryCharacter(character);
			ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
			if ((Object)(object)val2 == (Object)null || !val2.IsValid() || !val2.IsOwner())
			{
				return false;
			}
			Rigidbody component = ((Component)val).GetComponent<Rigidbody>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			m_ownedFreezes[character] = new OwnedFreeze
			{
				Player = val,
				Body = component,
				Constraints = component.constraints,
				Position = ((Component)val).transform.position,
				Rotation = ((Component)val).transform.rotation
			};
			component.constraints = (RigidbodyConstraints)126;
			if (!component.isKinematic)
			{
				component.linearVelocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
			}
			if (val == Player.m_localPlayer)
			{
				Feedback("An admin froze your character.", error: true);
			}
			return true;
		}

		private void RemoveOwnedFreeze(ZDOID character)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (m_ownedFreezes.TryGetValue(character, out var value))
			{
				if ((Object)(object)value.Body != (Object)null)
				{
					value.Body.constraints = value.Constraints;
				}
				m_ownedFreezes.Remove(character);
				if (value.Player == Player.m_localPlayer)
				{
					Feedback("Your character is unfrozen.");
				}
			}
		}

		private unsafe static void RPC_FreezeRequest(long sender, ZDOID character, bool frozen)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			if (DenyQuarantined(sender) || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)m_instance == (Object)null)
			{
				return;
			}
			if (!IsAdminSender(sender))
			{
				Reply(sender, "Permission denied: freeze is admin-only.", error: true);
				return;
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && character == ((Character)Player.m_localPlayer).GetZDOID())
			{
				Reply(sender, "The host is protected from freeze.", error: true);
				return;
			}
			ZDO val = ((!((ZDOID)(ref character)).IsNone()) ? ZDOMan.instance.GetZDO(character) : null);
			Player val2 = FindInventoryCharacter(character);
			GameObject val3 = ((val != null && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null);
			if (val == null || ((Object)(object)val2 == (Obje