Decompiled source of AdminMenu v0.9.6

plugins/AdminMenu.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SoftReferenceableAssets;
using Splatform;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AdminMenu
{
	internal static class AdminRights
	{
		internal static readonly HashSet<string> OwnCharacterCommands = new HashSet<string>
		{
			"confirmcheats", "fly", "nocost", "debugmode", "raiseskill", "resetskill", "resetcharacter", "exploremap", "resetmap", "goto",
			"spawn", "wind", "resetwind", "forcedelete", "env", "resetenv", "addstatus", "stopfire"
		};

		private static readonly FieldRef<ZNet, SyncedList> AdminList = AccessTools.FieldRefAccess<ZNet, SyncedList>("m_adminList");

		private static readonly Action<ZNet> SendAdminList = AccessTools.MethodDelegate<Action<ZNet>>(AccessTools.Method(typeof(ZNet), "SendAdminList", (Type[])null, (Type[])null), (object)null, true);

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

		private static int entriesFrame = -1;

		private static int adminFrame = -1;

		private static bool clientAdmin;

		private static int unlockedFrame = -1;

		private static bool unlocked;

		internal static bool CanEdit
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
				{
					return AdminList.Invoke(ZNet.instance) != null;
				}
				return false;
			}
		}

		internal static bool IsClientAdmin
		{
			get
			{
				if (Time.frameCount == adminFrame)
				{
					return clientAdmin;
				}
				adminFrame = Time.frameCount;
				clientAdmin = Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer() && Contains(ZNet.instance.GetAdminList(), ((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref UserInfo.GetLocalUser().UserId)/*cast due to .constrained prefix*/).ToString());
				return clientAdmin;
			}
		}

		internal static List<string> Entries
		{
			get
			{
				if (Time.frameCount == entriesFrame)
				{
					return entries;
				}
				entriesFrame = Time.frameCount;
				entries.Clear();
				if (CanEdit)
				{
					entries.AddRange(AdminList.Invoke(ZNet.instance).GetList());
				}
				return entries;
			}
		}

		internal static bool MayUsePanel
		{
			get
			{
				if (Unlocked)
				{
					if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer())
					{
						return IsClientAdmin;
					}
					return true;
				}
				return false;
			}
		}

		internal static bool Unlocked
		{
			get
			{
				if (Time.frameCount == unlockedFrame)
				{
					return unlocked;
				}
				unlockedFrame = Time.frameCount;
				return unlocked = ReadUnlocked();
			}
		}

		private static bool ReadUnlocked()
		{
			if (!Plugin.PanelLocked.Value)
			{
				return true;
			}
			string value = Plugin.UnlockedFor.Value;
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string text = LocalId();
			object obj;
			if (!Object.op_Implicit((Object)(object)Game.instance))
			{
				obj = null;
			}
			else
			{
				PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
				obj = ((playerProfile != null) ? playerProfile.GetName() : null);
			}
			string text2 = (string)obj;
			string[] array = value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string text3 = array[i].Trim();
				if ((text != null && Plain(text3) == Plain(text)) || (text2 != null && string.Equals(text3, text2, StringComparison.OrdinalIgnoreCase)))
				{
					return true;
				}
			}
			return false;
		}

		internal static string LocalId()
		{
			try
			{
				return ((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref UserInfo.GetLocalUser().UserId)/*cast due to .constrained prefix*/).ToString();
			}
			catch (Exception)
			{
				return null;
			}
		}

		internal static void LockPanel(bool keepMine)
		{
			string text = LocalId();
			if (keepMine && !string.IsNullOrEmpty(text))
			{
				string value = Plugin.UnlockedFor.Value;
				bool flag = false;
				string[] array = value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					if (Plain(array[i].Trim()) == Plain(text))
					{
						flag = true;
					}
				}
				if (!flag)
				{
					Plugin.UnlockedFor.Value = ((value.Trim().Length == 0) ? text : (value.Trim() + "," + text));
				}
			}
			Plugin.PanelLocked.Value = true;
			Plugin.Log("panel locked by its own button" + (keepMine ? (", still open for " + text) : ""));
		}

		internal static bool IsHost(string user)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || string.IsNullOrEmpty(user))
			{
				return false;
			}
			user = user.Trim();
			if (string.Equals(user, Game.instance.GetPlayerProfile().GetName(), StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return Plain(user) == Plain(((object)Unsafe.As<PlatformUserID, PlatformUserID>(ref UserInfo.GetLocalUser().UserId)/*cast due to .constrained prefix*/).ToString());
		}

		internal static bool Has(string id)
		{
			return Contains(CanEdit ? Entries : (Object.op_Implicit((Object)(object)ZNet.instance) ? ZNet.instance.GetAdminList() : entries), id);
		}

		internal static void Set(string id, bool admin)
		{
			if (!CanEdit || string.IsNullOrEmpty(id))
			{
				return;
			}
			SyncedList val = AdminList.Invoke(ZNet.instance);
			if (admin && !Contains(val.GetList(), id))
			{
				val.Add(id);
			}
			if (!admin)
			{
				foreach (string item in new List<string>(val.GetList()))
				{
					if (Plain(item) == Plain(id))
					{
						val.Remove(item);
					}
				}
			}
			entriesFrame = -1;
			SendAdminList(ZNet.instance);
		}

		private static bool Contains(List<string> list, string id)
		{
			string text = Plain(id);
			foreach (string item in list)
			{
				if (Plain(item) == text)
				{
					return true;
				}
			}
			return false;
		}

		internal static string Plain(string id)
		{
			id = (id ?? "").Trim();
			if (!id.StartsWith("Steam_", StringComparison.OrdinalIgnoreCase))
			{
				return id;
			}
			return id.Substring(6);
		}
	}
	internal static class Bookmarks
	{
		internal sealed class Mark
		{
			internal string World;

			internal string Name;

			internal Vector3 Place;
		}

		private static readonly string FilePath = Path.Combine(Paths.ConfigPath, "AdminMenu.bookmarks.txt");

		private static List<Mark> all;

		private static List<Mark> All
		{
			get
			{
				if (all == null)
				{
					Load();
				}
				return all;
			}
		}

		internal static string World
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return "";
				}
				return ZNet.instance.GetWorldName();
			}
		}

		internal static List<Mark> Here()
		{
			List<Mark> list = new List<Mark>();
			string world = World;
			foreach (Mark item in All)
			{
				if (item.World == world)
				{
					list.Add(item);
				}
			}
			return list;
		}

		internal static void Add(string name, Vector3 place)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			All.Add(new Mark
			{
				World = World,
				Name = Clean(name),
				Place = place
			});
			Save();
		}

		internal static void Remove(Mark mark)
		{
			All.Remove(mark);
			Save();
		}

		private static string Clean(string name)
		{
			name = (name ?? "").Replace('\t', ' ').Replace('\n', ' ').Replace('\r', ' ')
				.Trim();
			if (name.Length <= 0)
			{
				return L.T("bookmarks.default_name");
			}
			return name;
		}

		private static void Load()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			all = new List<Mark>();
			try
			{
				if (!File.Exists(FilePath))
				{
					return;
				}
				string[] array = File.ReadAllLines(FilePath);
				for (int i = 0; i < array.Length; i++)
				{
					string[] array2 = array[i].Split('\t');
					if (array2.Length >= 5 && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array2[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
					{
						all.Add(new Mark
						{
							World = array2[0],
							Name = array2[1],
							Place = new Vector3(result, result2, result3)
						});
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Error("bookmarks not read: " + ex.Message);
			}
		}

		private static void Save()
		{
			try
			{
				List<string> list = new List<string>();
				foreach (Mark item in all)
				{
					list.Add(string.Join("\t", item.World, item.Name, F(item.Place.x), F(item.Place.y), F(item.Place.z)));
				}
				File.WriteAllLines(FilePath, list);
			}
			catch (Exception ex)
			{
				Plugin.Error("bookmarks not saved: " + ex.Message);
			}
		}

		private static string F(float value)
		{
			return value.ToString("0.##", CultureInfo.InvariantCulture);
		}
	}
	internal sealed class CharacterAppearance
	{
		internal string Beard;

		internal string Hair;

		internal Vector3 Skin = Vector3.one;

		internal Vector3 HairColor = Vector3.one;

		internal int Model;

		internal void Apply(Player player)
		{
			//IL_0026: 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)
			player.SetPlayerModel(Model);
			((Humanoid)player).SetBeard(Beard);
			((Humanoid)player).SetHair(Hair);
			player.SetSkinColor(Skin);
			player.SetHairColor(HairColor);
		}

		internal static void Write(ZPackage p, CharacterAppearance appearance)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			p.Write(appearance != null);
			if (appearance != null)
			{
				p.Write(appearance.Beard);
				p.Write(appearance.Hair);
				p.Write(appearance.Skin);
				p.Write(appearance.HairColor);
				p.Write(appearance.Model);
			}
		}

		internal static CharacterAppearance Read(ZPackage p)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!p.ReadBool())
			{
				return null;
			}
			CharacterAppearance characterAppearance = new CharacterAppearance();
			characterAppearance.Beard = p.ReadString();
			characterAppearance.Hair = p.ReadString();
			characterAppearance.Skin = p.ReadVector3();
			characterAppearance.HairColor = p.ReadVector3();
			characterAppearance.Model = p.ReadInt();
			characterAppearance.Validate();
			return characterAppearance;
		}

		private void Validate()
		{
			if (Beard == null || Hair == null || Beard.Length > 256 || Hair.Length > 256 || Model < 0 || Model > 255)
			{
				throw new InvalidDataException("Invalid character appearance");
			}
			float[] array = new float[6] { Skin.x, Skin.y, Skin.z, HairColor.x, HairColor.y, HairColor.z };
			foreach (float num in array)
			{
				if (float.IsNaN(num) || float.IsInfinity(num) || Mathf.Abs(num) > 16f)
				{
					throw new InvalidDataException("Invalid character color");
				}
			}
		}

		internal static CharacterAppearance FromPlayerData(byte[] data)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Invalid comparison between Unknown and I4
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Invalid comparison between Unknown and I4
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Invalid comparison between Unknown and I4
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Invalid comparison between Unknown and I4
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Invalid comparison between Unknown and I4
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Invalid comparison between Unknown and I4
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Invalid comparison between Unknown and I4
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Invalid comparison between Unknown and I4
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Invalid comparison between Unknown and I4
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Invalid comparison between Unknown and I4
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Invalid comparison between Unknown and I4
			if (data == null)
			{
				return null;
			}
			if (data.Length < 4 || data.Length > 16777216)
			{
				throw new InvalidDataException("Invalid player data");
			}
			ZPackage val = new ZPackage(data);
			PlayerData val2 = (PlayerData)val.ReadInt();
			if ((int)val2 < 2 || (int)val2 > 34)
			{
				throw new InvalidDataException("Unsupported player appearance version");
			}
			if ((int)val2 < 4)
			{
				return null;
			}
			if ((int)val2 >= 7)
			{
				val.ReadSingle();
			}
			val.ReadSingle();
			if ((int)val2 >= 10)
			{
				val.ReadSingle();
			}
			if ((int)val2 >= 8 && (int)val2 < 28)
			{
				val.ReadBool();
			}
			if ((int)val2 >= 20)
			{
				val.ReadSingle();
			}
			if ((int)val2 >= 23)
			{
				val.ReadString();
			}
			if ((int)val2 >= 24)
			{
				val.ReadSingle();
			}
			SkipInventory(val);
			SkipStrings(val);
			int num = Count(val);
			for (int i = 0; i < num; i++)
			{
				val.ReadString();
				if ((int)val2 >= 15)
				{
					val.ReadInt();
				}
			}
			SkipStrings(val);
			if ((int)val2 < 19 || (int)val2 >= 21)
			{
				SkipStrings(val);
			}
			if ((int)val2 >= 6)
			{
				SkipStrings(val);
			}
			if ((int)val2 >= 9)
			{
				SkipStrings(val);
			}
			if ((int)val2 >= 18)
			{
				num = Count(val);
				for (int j = 0; j < num; j++)
				{
					if ((int)val2 >= 33 || (int)val2 == 31)
					{
						val.ReadString();
					}
					else
					{
						val.ReadInt();
					}
				}
			}
			if ((int)val2 >= 22)
			{
				num = Count(val);
				for (int k = 0; k < num; k++)
				{
					val.ReadString();
					val.ReadString();
				}
			}
			CharacterAppearance characterAppearance = new CharacterAppearance
			{
				Beard = val.ReadString(),
				Hair = val.ReadString()
			};
			if ((int)val2 >= 5)
			{
				characterAppearance.Skin = val.ReadVector3();
				characterAppearance.HairColor = val.ReadVector3();
			}
			if ((int)val2 >= 11)
			{
				characterAppearance.Model = val.ReadInt();
			}
			characterAppearance.Validate();
			return characterAppearance;
		}

		private static int Count(ZPackage p)
		{
			int num = p.ReadInt();
			if (num < 0 || num > 100000 || num > p.Size() - p.GetPos())
			{
				throw new InvalidDataException("Invalid appearance collection");
			}
			return num;
		}

		private static void SkipStrings(ZPackage p)
		{
			int num = Count(p);
			for (int i = 0; i < num; i++)
			{
				p.ReadString();
			}
		}

		private static void SkipInventory(ZPackage p)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_0078: 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_0088: Invalid comparison between Unknown and I4
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Invalid comparison between Unknown and I4
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Invalid comparison between Unknown and I4
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Invalid comparison between Unknown and I4
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Invalid comparison between Unknown and I4
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			Item val = (Item)p.ReadInt();
			if ((int)val > 110)
			{
				throw new InvalidDataException("Unsupported inventory version");
			}
			if ((int)val >= 108)
			{
				int num = p.ReadUShort();
				if (num > p.Size() - p.GetPos())
				{
					throw new InvalidDataException("Invalid inventory count");
				}
				for (int i = 0; i < num; i++)
				{
					ItemData.Load(p, val);
				}
				return;
			}
			int num2 = Count(p);
			for (int j = 0; j < num2; j++)
			{
				p.ReadString();
				p.ReadInt();
				p.ReadSingle();
				p.ReadVector2i();
				p.ReadBool();
				if ((int)val >= 101)
				{
					p.ReadInt();
				}
				if ((int)val >= 102)
				{
					p.ReadInt();
				}
				if ((int)val >= 103)
				{
					p.ReadLong();
					p.ReadString();
				}
				if ((int)val >= 104)
				{
					int num3 = Count(p);
					for (int k = 0; k < num3; k++)
					{
						p.ReadString();
						p.ReadString();
					}
				}
				if ((int)val >= 105)
				{
					p.ReadInt();
				}
				if ((int)val >= 106)
				{
					p.ReadBool();
				}
				if ((int)val == 107 || (int)val >= 109)
				{
					p.ReadBool();
				}
			}
		}
	}
	internal static class CharacterManualSavePolicy
	{
		internal static bool ShouldPush(int cooldownBefore, int cooldownAfter, long requestedBefore, long requestedAfter)
		{
			if (cooldownAfter > cooldownBefore)
			{
				return requestedBefore == requestedAfter;
			}
			return false;
		}
	}
	internal sealed class CharacterMapCodec
	{
		private int[] own;

		private int[] others;

		private int[] previousOwn;

		private int[] previousOthers;

		private byte[] raw;

		private byte[] previousTail;

		private byte[] cached;

		private int length;

		private int texture;

		private int previousTexture;

		private byte[] tail;

		internal void Capture(int size, BitArray explored, BitArray shared, byte[] pins)
		{
			if (explored == null || shared == null || explored.Length != shared.Length || explored.Length != checked(size * size))
			{
				throw new InvalidDataException("Invalid map dimensions");
			}
			int num = (explored.Length + 31) / 32;
			if (own == null || own.Length != num)
			{
				own = new int[num];
				others = new int[num];
				cached = null;
			}
			explored.CopyTo(own, 0);
			shared.CopyTo(others, 0);
			length = explored.Length;
			texture = size;
			tail = pins;
		}

		private static bool Equal(int[] a, int[] b)
		{
			if (b == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				if (a[i] != b[i])
				{
					return false;
				}
			}
			return true;
		}

		private static bool Equal(byte[] a, byte[] b)
		{
			if (b == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				if (a[i] != b[i])
				{
					return false;
				}
			}
			return true;
		}

		internal byte[] Encode()
		{
			if (cached != null && texture == previousTexture && Equal(own, previousOwn) && Equal(others, previousOthers) && Equal(tail, previousTail))
			{
				return cached;
			}
			int num = checked(4 + length * 2 + tail.Length);
			if (num > 16777216)
			{
				throw new InvalidDataException("Map is too large");
			}
			if (raw == null || raw.Length != num)
			{
				raw = new byte[num];
			}
			Buffer.BlockCopy(BitConverter.GetBytes(texture), 0, raw, 0, 4);
			Expand(own, raw, 4, length);
			Expand(others, raw, 4 + length, length);
			Buffer.BlockCopy(tail, 0, raw, 4 + length * 2, tail.Length);
			using (MemoryStream memoryStream = new MemoryStream())
			{
				using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionLevel.Fastest, leaveOpen: true))
				{
					gZipStream.Write(raw, 0, num);
				}
				byte[] array = memoryStream.ToArray();
				using MemoryStream memoryStream2 = new MemoryStream(8 + array.Length);
				using BinaryWriter binaryWriter = new BinaryWriter(memoryStream2);
				binaryWriter.Write(8);
				binaryWriter.Write(array.Length);
				binaryWriter.Write(array);
				cached = memoryStream2.ToArray();
			}
			if (previousOwn == null || previousOwn.Length != own.Length)
			{
				previousOwn = new int[own.Length];
				previousOthers = new int[others.Length];
			}
			Array.Copy(own, previousOwn, own.Length);
			Array.Copy(others, previousOthers, others.Length);
			previousTail = tail;
			previousTexture = texture;
			return cached;
		}

		private static void Expand(int[] bits, byte[] target, int offset, int count)
		{
			for (int i = 0; i < count; i++)
			{
				target[offset + i] = (byte)((bits[i >> 5] >>> i) & 1);
			}
		}
	}
	internal sealed class CharacterPayload
	{
		private readonly byte[] bytes;

		private readonly int mapOffset;

		internal CharacterPayload(byte[] captured, int offset)
		{
			bytes = captured;
			mapOffset = offset;
		}

		internal byte[] WithMap(byte[] map)
		{
			if (map == null)
			{
				return bytes;
			}
			int num = checked(bytes.Length + 4 + map.Length);
			if (num > 16777216)
			{
				throw new InvalidDataException("Character is too large");
			}
			using MemoryStream memoryStream = new MemoryStream(num);
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(bytes, 0, mapOffset);
			binaryWriter.Write(value: true);
			binaryWriter.Write(map.Length);
			binaryWriter.Write(map);
			binaryWriter.Write(bytes, mapOffset + 1, bytes.Length - mapOffset - 1);
			return memoryStream.ToArray();
		}
	}
	internal static class CharacterSnapshot
	{
		private const int Format = 2;

		private static readonly ConditionalWeakTable<PlayerProfile, CharacterAppearance> pendingAppearance = new ConditionalWeakTable<PlayerProfile, CharacterAppearance>();

		private static readonly FieldInfo PlayerData = typeof(PlayerProfile).GetField("m_playerData", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo PlayerId = typeof(PlayerProfile).GetField("m_playerID", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo Seed = typeof(PlayerProfile).GetField("m_startSeed", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo WorldData = typeof(PlayerProfile).GetMethod("GetWorldData", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly Type WorldDataType = typeof(PlayerProfile).GetNestedType("WorldPlayerData", BindingFlags.NonPublic);

		private static readonly string[] WorldFields = new string[8] { "m_haveCustomSpawnPoint", "m_spawnPoint", "m_haveLogoutPoint", "m_logoutPoint", "m_haveDeathPoint", "m_deathPoint", "m_homePoint", "m_mapData" };

		internal static CharacterAppearance Appearance(PlayerProfile profile)
		{
			if (!pendingAppearance.TryGetValue(profile, out var value))
			{
				return CharacterAppearance.FromPlayerData((byte[])PlayerData.GetValue(profile));
			}
			return value;
		}

		internal static bool HasPendingAppearance(PlayerProfile profile)
		{
			CharacterAppearance value;
			return pendingAppearance.TryGetValue(profile, out value);
		}

		internal static PlayerProfile Fresh(PlayerProfile original)
		{
			return Fresh(original, Appearance(original));
		}

		internal static PlayerProfile Fresh(PlayerProfile original, CharacterAppearance appearance)
		{
			//IL_0007: 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_0012: Expected O, but got Unknown
			PlayerProfile val = new PlayerProfile(original.GetFilename(), original.m_fileSource);
			val.SetName(original.GetName());
			PlayerId.SetValue(val, original.GetPlayerID());
			if (appearance != null)
			{
				pendingAppearance.Add(val, appearance);
			}
			return val;
		}

		internal static void ApplyAppearance(PlayerProfile profile, Player player)
		{
			if (pendingAppearance.TryGetValue(profile, out var value))
			{
				value.Apply(player);
				profile.SavePlayerData(player);
				pendingAppearance.Remove(profile);
				if (!string.IsNullOrEmpty(profile.GetFilename()) && !profile.Save())
				{
					throw new IOException("Could not save the character cache with preserved appearance");
				}
			}
		}

		internal static byte[] Encode(PlayerProfile profile, long world)
		{
			int mapOffset;
			return Encode(profile, world, omitMap: false, out mapOffset);
		}

		internal static CharacterPayload Capture(PlayerProfile profile, long world)
		{
			int mapOffset;
			return new CharacterPayload(Encode(profile, world, omitMap: true, out mapOffset), mapOffset);
		}

		private static byte[] Encode(PlayerProfile profile, long world, bool omitMap, out int mapOffset)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected I4, but got Unknown
			mapOffset = -1;
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(47);
			val.Write(world);
			val.Write(profile.GetName());
			val.Write(profile.GetPlayerID());
			val.Write(profile.m_firstSpawn);
			val.Write(profile.m_usedCheats);
			val.Write(profile.m_dateCreated.ToBinary());
			val.Write(((string)Seed.GetValue(profile)) ?? "");
			byte[] array = (byte[])PlayerData.GetValue(profile);
			val.Write(array != null);
			if (array != null)
			{
				val.Write(array);
			}
			object obj = WorldData.Invoke(profile, new object[1] { world });
			string[] worldFields = WorldFields;
			foreach (string text in worldFields)
			{
				object value = WorldDataType.GetField(text).GetValue(obj);
				if (text == "m_mapData")
				{
					mapOffset = val.Size();
					val.Write(!omitMap && value != null);
					if (!omitMap && value != null)
					{
						val.Write((byte[])value);
					}
				}
				else if (value is bool flag)
				{
					val.Write(flag);
				}
				else
				{
					val.Write((Vector3)value);
				}
			}
			val.Write(profile.m_playerStats.Length);
			PlayerStats[] playerStats = profile.m_playerStats;
			foreach (PlayerStats val2 in playerStats)
			{
				val.Write(val2.m_stats.Count);
				foreach (KeyValuePair<PlayerStatType, float> stat in val2.m_stats)
				{
					val.Write((int)stat.Key);
					val.Write(stat.Value);
				}
				WriteTable(val, val2.m_knownWorlds);
				WriteTable(val, val2.m_knownWorldKeys);
				WriteTable(val, val2.m_knownCommands);
				val.Write(val2.m_enemyStats.Length);
				Dictionary<string, float>[] enemyStats = val2.m_enemyStats;
				foreach (Dictionary<string, float> table in enemyStats)
				{
					WriteTable(val, table);
				}
				WriteTable(val, val2.m_itemPickupStats);
				WriteTable(val, val2.m_itemCraftStats);
				WriteTable(val, val2.m_pickableStats);
				WriteTable(val, val2.m_foodEatenStats);
				WriteTable(val, val2.m_piecesPlacedStats);
			}
			CharacterAppearance.Write(val, pendingAppearance.TryGetValue(profile, out var value2) ? value2 : null);
			byte[] array2 = val.GetArray();
			if (array2.Length > 16777216)
			{
				throw new InvalidDataException("Character is too large");
			}
			return array2;
		}

		internal static PlayerProfile Decode(byte[] bytes, string filename, FileSource source, long world)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			if (bytes == null || bytes.Length == 0 || bytes.Length > 16777216)
			{
				throw new InvalidDataException("Invalid character length");
			}
			ZPackage val = new ZPackage(bytes);
			int num = val.ReadInt();
			if (num != 1 && num != 2)
			{
				throw new InvalidDataException("Unknown snapshot format");
			}
			if (!Version.IsPlayerVersionCompatible((Player)val.ReadInt()))
			{
				throw new InvalidDataException("Incompatible Valheim character version");
			}
			if (val.ReadLong() != world)
			{
				throw new InvalidDataException("Character belongs to another world");
			}
			PlayerProfile val2 = new PlayerProfile(filename, source);
			val2.SetName(val.ReadString());
			PlayerId.SetValue(val2, val.ReadLong());
			val2.m_firstSpawn = val.ReadBool();
			val2.m_usedCheats = val.ReadBool();
			val2.m_dateCreated = DateTime.FromBinary(val.ReadLong());
			Seed.SetValue(val2, val.ReadString());
			if (val.ReadBool())
			{
				PlayerData.SetValue(val2, ReadBlob(val));
			}
			object obj = WorldData.Invoke(val2, new object[1] { world });
			string[] worldFields = WorldFields;
			foreach (string text in worldFields)
			{
				FieldInfo field = WorldDataType.GetField(text);
				object value = ((text == "m_mapData") ? (val.ReadBool() ? ReadBlob(val) : null) : ((field.FieldType == typeof(bool)) ? ((object)val.ReadBool()) : ((object)val.ReadVector3())));
				field.SetValue(obj, value);
			}
			if (val.ReadInt() != val2.m_playerStats.Length)
			{
				throw new InvalidDataException("Invalid statistics count");
			}
			PlayerStats[] playerStats = val2.m_playerStats;
			foreach (PlayerStats val3 in playerStats)
			{
				int num2 = Count(val);
				for (int j = 0; j < num2; j++)
				{
					val3.m_stats[(PlayerStatType)val.ReadInt()] = val.ReadSingle();
				}
				ReadTable(val, val3.m_knownWorlds);
				ReadTable(val, val3.m_knownWorldKeys);
				ReadTable(val, val3.m_knownCommands);
				if (val.ReadInt() != val3.m_enemyStats.Length)
				{
					throw new InvalidDataException("Invalid enemy statistics count");
				}
				Dictionary<string, float>[] enemyStats = val3.m_enemyStats;
				foreach (Dictionary<string, float> table in enemyStats)
				{
					ReadTable(val, table);
				}
				ReadTable(val, val3.m_itemPickupStats);
				ReadTable(val, val3.m_itemCraftStats);
				ReadTable(val, val3.m_pickableStats);
				ReadTable(val, val3.m_foodEatenStats);
				ReadTable(val, val3.m_piecesPlacedStats);
			}
			if (num >= 2)
			{
				CharacterAppearance characterAppearance = CharacterAppearance.Read(val);
				if (characterAppearance != null)
				{
					pendingAppearance.Add(val2, characterAppearance);
				}
			}
			if (val.GetPos() != val.Size())
			{
				throw new InvalidDataException("Unexpected snapshot data");
			}
			return val2;
		}

		private static int Count(ZPackage p)
		{
			int num = p.ReadInt();
			if (num < 0 || num > 100000 || num > p.Size() - p.GetPos())
			{
				throw new InvalidDataException("Invalid collection size");
			}
			return num;
		}

		internal static byte[] ReadBlob(ZPackage p)
		{
			int pos = p.GetPos();
			int num = p.ReadInt();
			if (num < 0 || num > 16777216 || num > p.Size() - p.GetPos())
			{
				throw new InvalidDataException("Invalid byte array length");
			}
			p.SetPos(pos);
			return p.ReadByteArray();
		}

		private static void WriteTable(ZPackage p, Dictionary<string, float> table)
		{
			p.Write(table.Count);
			foreach (KeyValuePair<string, float> item in table)
			{
				p.Write(item.Key);
				p.Write(item.Value);
			}
		}

		private static void ReadTable(ZPackage p, Dictionary<string, float> table)
		{
			table.Clear();
			int num = Count(p);
			for (int i = 0; i < num; i++)
			{
				table.Add(p.ReadString(), p.ReadSingle());
			}
		}
	}
	internal static class CharacterStorage
	{
		internal const int MaxBytes = 16777216;

		private const int Magic = 1095582513;

		private static readonly object[] gates = MakeGates();

		private static object[] MakeGates()
		{
			object[] array = new object[32];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new object();
			}
			return array;
		}

		private static object Gate(string path)
		{
			return gates[(StringComparer.OrdinalIgnoreCase.GetHashCode(Path.GetFullPath(path)) & 0x7FFFFFFF) % gates.Length];
		}

		internal static string Hash(string text)
		{
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "").ToLowerInvariant();
		}

		internal static byte[] Read(string path)
		{
			lock (Gate(path))
			{
				return ReadCore(path);
			}
		}

		private static byte[] ReadCore(string path)
		{
			using FileStream fileStream = File.OpenRead(path);
			using BinaryReader binaryReader = new BinaryReader(fileStream);
			if (fileStream.Length < 40)
			{
				throw new InvalidDataException("Truncated character file");
			}
			if (binaryReader.ReadInt32() != 1095582513)
			{
				throw new InvalidDataException("Unknown character file format");
			}
			int num = binaryReader.ReadInt32();
			if (num <= 0 || num > 16777216 || fileStream.Length != (long)num + 40L)
			{
				throw new InvalidDataException("Invalid character file length");
			}
			byte[] array = binaryReader.ReadBytes(32);
			byte[] array2 = binaryReader.ReadBytes(num);
			using (SHA256 sHA = SHA256.Create())
			{
				if (BitConverter.ToString(array) != BitConverter.ToString(sHA.ComputeHash(array2)))
				{
					throw new InvalidDataException("Character file checksum mismatch");
				}
			}
			return array2;
		}

		internal static void Write(string path, byte[] data)
		{
			lock (Gate(path))
			{
				WriteCore(path, data);
			}
		}

		private static void WriteCore(string path, byte[] data)
		{
			if (data == null || data.Length == 0 || data.Length > 16777216)
			{
				throw new InvalidDataException("Character is too large");
			}
			Directory.CreateDirectory(Path.GetDirectoryName(path));
			string text = path + ".new";
			using (FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None))
			{
				using BinaryWriter binaryWriter = new BinaryWriter(fileStream);
				using SHA256 sHA = SHA256.Create();
				binaryWriter.Write(1095582513);
				binaryWriter.Write(data.Length);
				binaryWriter.Write(sHA.ComputeHash(data));
				binaryWriter.Write(data);
				binaryWriter.Flush();
				fileStream.Flush(flushToDisk: true);
			}
			if (File.Exists(path))
			{
				File.Replace(text, path, path + ".old", ignoreMetadataErrors: true);
			}
			else
			{
				File.Move(text, path);
			}
		}
	}
	internal static class CharacterWorkQueue
	{
		private static Task tail = Task.FromResult(0);

		internal static bool IsIdle => tail.IsCompleted;

		internal static Task<T> Run<T>(Func<T> action)
		{
			return (Task<T>)(tail = tail.ContinueWith(delegate(Task previous)
			{
				if (previous.IsFaulted)
				{
					_ = previous.Exception;
				}
				return action();
			}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default));
		}
	}
	internal static class Commands
	{
		private const int LogLimit = 80;

		internal static readonly List<string> Log = new List<string>();

		internal static int LogVersion;

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

		private static Dictionary<string, ConsoleCommand> table;

		private static Dictionary<string, ConsoleCommand> Table => table ?? (table = (Dictionary<string, ConsoleCommand>)AccessTools.Field(typeof(Terminal), "commands").GetValue(null));

		internal static string Blocker(string name)
		{
			Console instance = Console.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Table.TryGetValue(name, out var value))
			{
				return L.F("block.no_command", name);
			}
			if (value.IsCheat && !Terminal.m_cheat)
			{
				return L.T("block.cheats_off");
			}
			if (value.RemoteCommand && Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer())
			{
				return null;
			}
			if (!value.IsValid((Terminal)(object)instance, false))
			{
				if (value.IsCheat && Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer() && !AdminRights.IsClientAdmin)
				{
					return L.T("block.need_rights");
				}
				return L.T("block.host_only");
			}
			if (value.IsCheat && name != "confirmcheats" && !Achievements.IsCheatedAtAll())
			{
				return L.T("block.confirm_cheats");
			}
			return null;
		}

		internal static bool IsCheat(string name)
		{
			if (Table.TryGetValue(name, out var value))
			{
				return value.IsCheat;
			}
			return false;
		}

		internal static bool Exists(string name)
		{
			if (Object.op_Implicit((Object)(object)Console.instance))
			{
				return Table.ContainsKey(name);
			}
			return false;
		}

		internal static void Run(string line)
		{
			queue.Add(line);
		}

		internal static void RunDirect(string line)
		{
			if (Object.op_Implicit((Object)(object)Console.instance))
			{
				AddLog("<color=#8a857c>» " + line + "</color>");
				((Terminal)Console.instance).TryRunCommand(line, false, false);
			}
		}

		internal static void Flush()
		{
			if (queue.Count == 0)
			{
				return;
			}
			string[] array = queue.ToArray();
			queue.Clear();
			if (Object.op_Implicit((Object)(object)Console.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				string[] array2 = array;
				foreach (string text in array2)
				{
					AddLog("<color=#8a857c>» " + text + "</color>");
					((Terminal)Console.instance).TryRunCommand(text, false, false);
				}
			}
		}

		internal static void AddLog(string text)
		{
			if (!string.IsNullOrEmpty(text) && (Object.op_Implicit((Object)(object)Player.m_localPlayer) || Object.op_Implicit((Object)(object)FejdStartup.instance)))
			{
				Log.Add(text.TrimEnd());
				if (Log.Count > 80)
				{
					Log.RemoveRange(0, Log.Count - 80);
				}
				LogVersion++;
			}
		}
	}
	internal static class CreatureIcons
	{
		private const int Size = 128;

		private const int Layer = 31;

		private const int PerFrame = 2;

		private static readonly Vector3 Stage = new Vector3(0f, 5000f, 0f);

		private static readonly Dictionary<GameObject, Sprite> done = new Dictionary<GameObject, Sprite>();

		private static readonly List<GameObject> wanted = new List<GameObject>();

		private static Camera camera;

		private static Light light;

		private static RenderTexture target;

		internal static Sprite Get(GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			if (done.TryGetValue(prefab, out var value))
			{
				return value;
			}
			if (!wanted.Contains(prefab))
			{
				wanted.Add(prefab);
			}
			return null;
		}

		internal static void Update()
		{
			for (int i = 0; i < 2; i++)
			{
				if (wanted.Count <= 0)
				{
					break;
				}
				GameObject val = wanted[0];
				wanted.RemoveAt(0);
				Sprite value = null;
				try
				{
					value = Render(val);
				}
				catch (Exception ex)
				{
					Plugin.Log("no icon for " + (Object.op_Implicit((Object)(object)val) ? ((Object)val).name : "?") + ": " + ex.Message);
				}
				if (Object.op_Implicit((Object)(object)val))
				{
					done[val] = value;
				}
			}
		}

		private static Sprite Render(GameObject prefab)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_001d: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			Setup();
			GameObject val = new GameObject("AdminMenu icon");
			val.SetActive(false);
			val.transform.position = Stage;
			bool forceDisableInit = ZNetView.m_forceDisableInit;
			ZNetView.m_forceDisableInit = true;
			GameObject val2;
			try
			{
				val2 = Object.Instantiate<GameObject>(prefab, val.transform, false);
			}
			finally
			{
				ZNetView.m_forceDisableInit = forceDisableInit;
			}
			try
			{
				Strip(val2);
				if (val2.GetComponentsInChildren<MonoBehaviour>(true).Length != 0)
				{
					return null;
				}
				val2.transform.localPosition = Vector3.zero;
				val2.transform.localRotation = Quaternion.Euler(0f, 145f, 0f);
				Transform[] componentsInChildren = val2.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = 31;
				}
				val.SetActive(true);
				Animator[] componentsInChildren2 = val2.GetComponentsInChildren<Animator>();
				foreach (Animator obj in componentsInChildren2)
				{
					obj.cullingMode = (AnimatorCullingMode)0;
					obj.Update(0.1f);
				}
				if (!Bounds(val2, out var bounds))
				{
					return null;
				}
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				float num = Mathf.Max(0.1f, ((Vector3)(ref extents)).magnitude);
				float num2 = num / Mathf.Sin(camera.fieldOfView * 0.5f * ((float)Math.PI / 180f));
				((Component)camera).transform.rotation = Quaternion.Euler(12f, 0f, 0f);
				((Component)camera).transform.position = ((Bounds)(ref bounds)).center - ((Component)camera).transform.forward * num2;
				camera.nearClipPlane = Mathf.Max(0.01f, num2 - num * 1.5f);
				camera.farClipPlane = num2 + num * 1.5f;
				((Component)light).transform.rotation = Quaternion.Euler(35f, -30f, 0f);
				((Behaviour)light).enabled = true;
				camera.Render();
				((Behaviour)light).enabled = false;
				RenderTexture active = RenderTexture.active;
				RenderTexture.active = target;
				Texture2D val3 = new Texture2D(128, 128, (TextureFormat)4, false)
				{
					hideFlags = (HideFlags)61
				};
				val3.ReadPixels(new Rect(0f, 0f, 128f, 128f), 0, 0);
				val3.Apply(false, false);
				RenderTexture.active = active;
				return Sprite.Create(val3, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
			}
			finally
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}

		private static void Strip(GameObject copy)
		{
			for (int i = 0; i < 4; i++)
			{
				MonoBehaviour[] componentsInChildren = copy.GetComponentsInChildren<MonoBehaviour>(true);
				if (componentsInChildren.Length == 0)
				{
					break;
				}
				for (int num = componentsInChildren.Length - 1; num >= 0; num--)
				{
					if (Object.op_Implicit((Object)(object)componentsInChildren[num]) && CanRemove(componentsInChildren[num]))
					{
						Object.DestroyImmediate((Object)(object)componentsInChildren[num]);
					}
				}
			}
			ParticleSystem[] componentsInChildren2 = copy.GetComponentsInChildren<ParticleSystem>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				((Component)componentsInChildren2[j]).gameObject.SetActive(false);
			}
			Light[] componentsInChildren3 = copy.GetComponentsInChildren<Light>(true);
			for (int j = 0; j < componentsInChildren3.Length; j++)
			{
				((Behaviour)componentsInChildren3[j]).enabled = false;
			}
			AudioSource[] componentsInChildren4 = copy.GetComponentsInChildren<AudioSource>(true);
			for (int j = 0; j < componentsInChildren4.Length; j++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[j]);
			}
			Joint[] componentsInChildren5 = copy.GetComponentsInChildren<Joint>(true);
			for (int j = 0; j < componentsInChildren5.Length; j++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[j]);
			}
			Rigidbody[] componentsInChildren6 = copy.GetComponentsInChildren<Rigidbody>(true);
			for (int j = 0; j < componentsInChildren6.Length; j++)
			{
				componentsInChildren6[j].isKinematic = true;
			}
			Collider[] componentsInChildren7 = copy.GetComponentsInChildren<Collider>(true);
			for (int j = 0; j < componentsInChildren7.Length; j++)
			{
				componentsInChildren7[j].enabled = false;
			}
		}

		private static bool CanRemove(MonoBehaviour script)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			MonoBehaviour[] components = ((Component)script).GetComponents<MonoBehaviour>();
			foreach (MonoBehaviour val in components)
			{
				if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val == (Object)(object)script)
				{
					continue;
				}
				object[] customAttributes = ((object)val).GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true);
				for (int j = 0; j < customAttributes.Length; j++)
				{
					RequireComponent val2 = (RequireComponent)customAttributes[j];
					Type type = ((object)script).GetType();
					if ((val2.m_Type0 != null && val2.m_Type0.IsAssignableFrom(type)) || (val2.m_Type1 != null && val2.m_Type1.IsAssignableFrom(type)) || (val2.m_Type2 != null && val2.m_Type2.IsAssignableFrom(type)))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool Bounds(GameObject copy, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = copy.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (val.enabled && !(val is ParticleSystemRenderer))
				{
					if (!flag)
					{
						bounds = val.bounds;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
					flag = true;
				}
			}
			if (flag)
			{
				Vector3 size = ((Bounds)(ref bounds)).size;
				return ((Vector3)(ref size)).sqrMagnitude > 0.0001f;
			}
			return false;
		}

		private static void Setup()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)camera))
			{
				GameObject val = new GameObject("AdminMenu icon camera")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val);
				target = new RenderTexture(128, 128, 24, (RenderTextureFormat)0)
				{
					antiAliasing = 4,
					hideFlags = (HideFlags)61
				};
				camera = val.AddComponent<Camera>();
				((Behaviour)camera).enabled = false;
				camera.cullingMask = int.MinValue;
				camera.clearFlags = (CameraClearFlags)2;
				camera.backgroundColor = new Color(0f, 0f, 0f, 0f);
				camera.fieldOfView = 25f;
				camera.allowHDR = false;
				camera.allowMSAA = true;
				camera.targetTexture = target;
				GameObject val2 = new GameObject("AdminMenu icon light")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val2);
				light = val2.AddComponent<Light>();
				light.type = (LightType)1;
				light.intensity = 1.3f;
				light.cullingMask = int.MinValue;
				((Behaviour)light).enabled = false;
			}
		}
	}
	internal static class DropRules
	{
		internal static Dictionary<string, List<DropCellRule>> Rules = new Dictionary<string, List<DropCellRule>>();

		private static readonly Dictionary<CharacterDrop, List<Drop>> originals = new Dictionary<CharacterDrop, List<Drop>>();

		private static readonly HashSet<CharacterDrop> changed = new HashSet<CharacterDrop>();

		private static readonly HashSet<string> reported = new HashSet<string>();

		private static ZNetScene appliedScene;

		internal static bool Stale
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					return appliedScene != ZNetScene.instance;
				}
				return false;
			}
		}

		internal static void Apply()
		{
			foreach (CharacterDrop item in changed)
			{
				if (Object.op_Implicit((Object)(object)item) && originals.TryGetValue(item, out var value))
				{
					item.m_drops = new List<Drop>(value);
				}
			}
			changed.Clear();
			ZNetScene val = (appliedScene = ZNetScene.instance);
			if (!Object.op_Implicit((Object)(object)val) || Rules.Count == 0)
			{
				return;
			}
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.Ordinal);
			if (Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				foreach (GameObject item2 in ObjectDB.instance.m_items)
				{
					if (Object.op_Implicit((Object)(object)item2))
					{
						dictionary[((Object)item2).name.ToLowerInvariant()] = item2;
					}
				}
			}
			Dictionary<string, List<Drop>> dictionary2 = new Dictionary<string, List<Drop>>(StringComparer.Ordinal);
			foreach (GameObject prefab in val.m_prefabs)
			{
				if (Object.op_Implicit((Object)(object)prefab) && Rules.TryGetValue(((Object)prefab).name.ToLowerInvariant(), out var value2))
				{
					CharacterDrop component = prefab.GetComponent<CharacterDrop>();
					if (!Object.op_Implicit((Object)(object)component))
					{
						Report("drop list on " + ((Object)prefab).name);
						continue;
					}
					List<Drop> value3 = (component.m_drops = Build(Remember(component), value2, dictionary, ((Object)prefab).name));
					changed.Add(component);
					dictionary2[((Object)prefab).name] = value3;
				}
			}
			CharacterDrop[] array = Object.FindObjectsByType<CharacterDrop>((FindObjectsSortMode)0);
			foreach (CharacterDrop val2 in array)
			{
				if (Object.op_Implicit((Object)(object)val2) && dictionary2.TryGetValue(Utils.GetPrefabName(((Component)val2).gameObject), out var value4))
				{
					Remember(val2);
					val2.m_drops = new List<Drop>(value4);
					changed.Add(val2);
				}
			}
		}

		internal static List<DropCellRule> Original(GameObject prefab)
		{
			List<DropCellRule> list = new List<DropCellRule>();
			CharacterDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<CharacterDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return list;
			}
			List<Drop> value;
			List<Drop> list2 = (originals.TryGetValue(val, out value) ? value : val.m_drops);
			if (list2 != null)
			{
				foreach (Drop item in list2)
				{
					if (Object.op_Implicit((Object)(object)item?.m_prefab))
					{
						list.Add(new DropCellRule(((Object)item.m_prefab).name, item.m_amountMin, item.m_amountMax, item.m_chance));
					}
				}
			}
			return list;
		}

		internal static bool HasDropList(GameObject prefab)
		{
			if (Object.op_Implicit((Object)(object)prefab))
			{
				return Object.op_Implicit((Object)(object)prefab.GetComponent<CharacterDrop>());
			}
			return false;
		}

		internal static void Set(string prefab, List<DropCellRule> cells, RuleScope scope)
		{
			Dictionary<string, List<DropCellRule>> dictionary = new Dictionary<string, List<DropCellRule>>(WorldRules.Layer(scope).Drops);
			string key = prefab.ToLowerInvariant();
			GameObject prefab2 = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefab) : null);
			if (cells == null || DropRuleText.Same(cells, Original(prefab2)))
			{
				dictionary.Remove(key);
			}
			else
			{
				dictionary[key] = cells;
			}
			WorldRules.SetDrops(scope, DropRuleText.FormatTable(dictionary));
		}

		private static List<Drop> Remember(CharacterDrop drop)
		{
			if (!originals.TryGetValue(drop, out var value))
			{
				value = (originals[drop] = new List<Drop>(drop.m_drops ?? new List<Drop>()));
			}
			return value;
		}

		private static List<Drop> Build(List<Drop> original, List<DropCellRule> cells, Dictionary<string, GameObject> items, string creature)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			List<Drop> list = new List<Drop>();
			foreach (DropCellRule cell in cells)
			{
				if (!items.TryGetValue(cell.Item, out var item))
				{
					Report("item " + cell.Item + " for " + creature);
					continue;
				}
				Drop val = original.Find((Drop d) => d != null && (Object)(object)d.m_prefab == (Object)(object)item);
				list.Add(new Drop
				{
					m_prefab = item,
					m_amountMin = cell.Min,
					m_amountMax = cell.Max,
					m_chance = cell.Chance,
					m_onePerPlayer = (val?.m_onePerPlayer ?? false),
					m_levelMultiplier = (val?.m_levelMultiplier ?? true),
					m_levelMultiplierNotAmount = (val?.m_levelMultiplierNotAmount ?? false),
					m_dontScale = (val?.m_dontScale ?? false)
				});
			}
			return list;
		}

		private static void Report(string what)
		{
			if (reported.Add(what))
			{
				Plugin.Warning("drop rule: no " + what + " in this game; left as it was");
			}
		}
	}
	internal struct DropCellRule : IEquatable<DropCellRule>
	{
		internal string Item;

		internal int Min;

		internal int Max;

		internal float Chance;

		internal DropCellRule(string item, int min, int max, float chance)
		{
			Item = (item ?? "").ToLowerInvariant();
			Min = Math.Max(0, Math.Min(min, 10000));
			Max = Math.Max(Min, Math.Min(max, 10000));
			Chance = (float.IsNaN(chance) ? 0f : Math.Max(0f, Math.Min(chance, 1f)));
		}

		public bool Equals(DropCellRule other)
		{
			if (Item == other.Item && Min == other.Min && Max == other.Max)
			{
				return Math.Abs(Chance - other.Chance) < 5E-05f;
			}
			return false;
		}

		public override bool Equals(object other)
		{
			if (other is DropCellRule other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (Item ?? "").GetHashCode() ^ (Min * 31) ^ (Max * 977);
		}
	}
	internal static class DropRuleText
	{
		internal const int MaxCells = 128;

		internal const int MaxAmount = 10000;

		internal static string Encode(List<DropCellRule> cells)
		{
			if (cells.Count == 0)
			{
				return "-";
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < cells.Count && i < 128; i++)
			{
				DropCellRule dropCellRule = cells[i];
				if (i > 0)
				{
					stringBuilder.Append('/');
				}
				stringBuilder.Append(dropCellRule.Item).Append('*').Append(dropCellRule.Min)
					.Append('*')
					.Append(dropCellRule.Max)
					.Append('*')
					.Append(dropCellRule.Chance.ToString("0.####", CultureInfo.InvariantCulture));
			}
			return stringBuilder.ToString();
		}

		internal static List<DropCellRule> Decode(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			List<DropCellRule> list = new List<DropCellRule>();
			if (text.Trim() == "-")
			{
				return list;
			}
			string[] array = text.Split('/');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('*');
				if (array2.Length != 4 || array2[0].Trim().Length == 0 || !int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array2[2].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array2[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
				{
					return null;
				}
				if (list.Count < 128)
				{
					list.Add(new DropCellRule(array2[0].Trim(), result, result2, result3));
				}
			}
			return list;
		}

		internal static Dictionary<string, List<DropCellRule>> ParseTable(string raw)
		{
			Dictionary<string, List<DropCellRule>> dictionary = new Dictionary<string, List<DropCellRule>>(StringComparer.Ordinal);
			if (string.IsNullOrEmpty(raw))
			{
				return dictionary;
			}
			string[] array = raw.Split(';');
			foreach (string text in array)
			{
				int num = text.IndexOf('=');
				if (num > 0)
				{
					List<DropCellRule> list = Decode(text.Substring(num + 1).Trim());
					if (list != null)
					{
						dictionary[text.Substring(0, num).Trim().ToLowerInvariant()] = list;
					}
				}
			}
			return dictionary;
		}

		internal static string FormatTable(IDictionary<string, List<DropCellRule>> rules)
		{
			if (rules.Count == 0)
			{
				return null;
			}
			SortedDictionary<string, List<DropCellRule>> sortedDictionary = new SortedDictionary<string, List<DropCellRule>>(StringComparer.Ordinal);
			foreach (KeyValuePair<string, List<DropCellRule>> rule in rules)
			{
				sortedDictionary[rule.Key.ToLowerInvariant()] = rule.Value;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, List<DropCellRule>> item in sortedDictionary)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(';');
				}
				stringBuilder.Append(item.Key).Append('=').Append(Encode(item.Value));
			}
			return stringBuilder.ToString();
		}

		internal static bool Same(List<DropCellRule> a, List<DropCellRule> b)
		{
			if (a == null || b == null || a.Count != b.Count)
			{
				return false;
			}
			for (int i = 0; i < a.Count; i++)
			{
				if (!a[i].Equals(b[i]))
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class Effects
	{
		internal sealed class Entry
		{
			internal string Asset;

			internal string Name;

			internal string Category;

			internal int Hash;

			internal float Duration;

			internal Sprite Icon;
		}

		internal const string Good = "fx.cat_good";

		internal const string Powers = "fx.cat_powers";

		internal const string Bad = "fx.cat_bad";

		internal static readonly string[] Categories = new string[3] { "fx.cat_good", "fx.cat_powers", "fx.cat_bad" };

		private static readonly HashSet<string> BadTypes = new HashSet<string> { "SE_Burning", "SE_Frost", "SE_Harpooned", "SE_Poison", "SE_Puke", "SE_Smoke", "SE_Wet" };

		private static readonly HashSet<string> BadNames = new HashSet<string>
		{
			"Cold", "Freezing", "Encumbered", "Tared", "Wet", "Smoked", "Burning", "Poison", "Frost", "Lightning",
			"Spirit", "Slimed", "Staggering"
		};

		internal static readonly List<Entry> All = new List<Entry>();

		private static ObjectDB readFrom;

		private static int readCount = -1;

		internal static void Forget()
		{
			readFrom = null;
		}

		internal static void Refresh()
		{
			ObjectDB instance = ObjectDB.instance;
			if (!Object.op_Implicit((Object)(object)instance) || (instance == readFrom && instance.m_StatusEffects.Count == readCount))
			{
				return;
			}
			readFrom = instance;
			readCount = instance.m_StatusEffects.Count;
			All.Clear();
			foreach (StatusEffect statusEffect in instance.m_StatusEffects)
			{
				if (Object.op_Implicit((Object)(object)statusEffect))
				{
					string text = ((string.IsNullOrEmpty(statusEffect.m_name) || Localization.instance == null) ? "" : Localization.instance.Localize(statusEffect.m_name));
					if (string.IsNullOrEmpty(text) || text.StartsWith("["))
					{
						text = ((Object)statusEffect).name;
					}
					All.Add(new Entry
					{
						Asset = ((Object)statusEffect).name,
						Name = text,
						Hash = StringExtensionMethods.GetStableHashCode(((Object)statusEffect).name),
						Duration = statusEffect.m_ttl,
						Icon = statusEffect.m_icon,
						Category = (((Object)statusEffect).name.StartsWith("GP_") ? "fx.cat_powers" : ((BadTypes.Contains(((object)statusEffect).GetType().Name) || BadNames.Contains(((Object)statusEffect).name)) ? "fx.cat_bad" : "fx.cat_good"))
					});
				}
			}
			All.Sort((Entry a, Entry b) => string.Compare(a.Name, b.Name, StringComparison.CurrentCulture));
		}

		internal static void Apply(Entry entry, Character target, float duration)
		{
			Apply(entry.Hash, entry.Name, target, duration);
		}

		internal static void Apply(int hash, string name, Character target, float duration)
		{
			SEMan val = (Object.op_Implicit((Object)(object)target) ? target.GetSEMan() : null);
			if (val != null)
			{
				val.AddStatusEffect(hash, true, 0, 0f, (short)(-1));
				StatusEffect val2 = (Owned(target) ? val.GetStatusEffect(hash) : null);
				if (Object.op_Implicit((Object)(object)val2) && duration > 0f)
				{
					val2.m_ttl = duration;
					val2.ResetTime();
				}
				Commands.AddLog("<color=#8a857c>» " + L.F("log.effect", name, Name(target)) + ((duration > 0f && Object.op_Implicit((Object)(object)val2)) ? (", " + L.F("unit.seconds", Mathf.RoundToInt(duration))) : "") + "</color>");
			}
		}

		internal static void Remove(StatusEffect effect, Character target)
		{
			if (Object.op_Implicit((Object)(object)target) && Owned(target))
			{
				target.GetSEMan().RemoveStatusEffect(effect, false);
			}
		}

		internal static bool Owned(Character target)
		{
			ZNetView val = (Object.op_Implicit((Object)(object)target) ? ((Component)target).GetComponent<ZNetView>() : null);
			if (Object.op_Implicit((Object)(object)val) && val.IsValid())
			{
				return val.IsOwner();
			}
			return false;
		}

		internal static string Name(Character target)
		{
			if (!Object.op_Implicit((Object)(object)target))
			{
				return "—";
			}
			if ((Object)(object)target == (Object)(object)Player.m_localPlayer)
			{
				return L.T("fx.you");
			}
			Player val = (Player)(object)((target is Player) ? target : null);
			if (val != null)
			{
				return val.GetPlayerName();
			}
			if (Localization.instance == null)
			{
				return target.m_name;
			}
			return Localization.instance.Localize(target.m_name);
		}
	}
	internal static class FreeFlyLoader
	{
		private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude");

		private static Player held;

		private static ZNetView heldView;

		private static Rigidbody heldBody;

		private static Vector3 anchor;

		private static bool cameraLeads;

		private static float returnedAt;

		internal static string Note { get; private set; }

		internal static string Unavailable()
		{
			if (!Object.op_Implicit((Object)(object)Console.instance) || !((Terminal)Console.instance).IsCheatsEnabled())
			{
				return L.T("freefly.need_cheats");
			}
			return null;
		}

		internal static void Tick()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (held != null && (!Object.op_Implicit((Object)(object)held) || (Object)(object)held != (Object)(object)localPlayer))
			{
				Forget();
			}
			bool flag = Object.op_Implicit((Object)(object)localPlayer) && WantsLead(localPlayer);
			if (flag && !cameraLeads)
			{
				if (held == null)
				{
					Grab(localPlayer);
				}
				cameraLeads = true;
			}
			else if (!flag && cameraLeads)
			{
				cameraLeads = false;
				returnedAt = Time.time;
			}
			if (held != null && !cameraLeads)
			{
				float num = Time.time - returnedAt;
				if ((num > 0.5f && Object.op_Implicit((Object)(object)ZNetScene.instance) && ZNetScene.instance.IsAreaReady(anchor)) || num > 15f || ((Character)held).IsDead() || ((Character)held).IsTeleporting())
				{
					Release();
				}
			}
		}

		private static bool WantsLead(Player player)
		{
			Note = null;
			if (!GameCamera.InFreeFly() || !Plugin.FreeFlyLoadsWorld.Value || Unavailable() != null)
			{
				return false;
			}
			if (((Character)player).IsDead() || ((Character)player).IsTeleporting())
			{
				return false;
			}
			if (cameraLeads)
			{
				return true;
			}
			if (((Character)player).IsAttached() || (Object)(object)((Character)player).GetStandingOnShip() != (Object)null)
			{
				Note = L.T("freefly.attached");
				return false;
			}
			return true;
		}

		private static void Grab(Player player)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			held = player;
			heldView = ((Component)player).GetComponent<ZNetView>();
			heldBody = ((Component)player).GetComponent<Rigidbody>();
			anchor = ((Component)player).transform.position;
		}

		private static void Release()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)held))
			{
				MaxAirAltitude.Invoke((Character)(object)held) = ((Component)held).transform.position.y;
			}
			Forget();
		}

		private static void Forget()
		{
			held = null;
			heldView = null;
			heldBody = null;
			cameraLeads = false;
		}

		internal static void Hold()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)held) && !((Character)held).IsTeleporting())
			{
				((Component)held).transform.position = anchor;
				if (Object.op_Implicit((Object)(object)heldBody))
				{
					heldBody.linearVelocity = Vector3.zero;
					heldBody.angularVelocity = Vector3.zero;
				}
			}
		}

		internal static void MoveReference()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (cameraLeads && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)GameCamera.instance))
			{
				ZNet.instance.SetReferencePosition(((Component)GameCamera.instance).transform.position);
			}
		}

		internal static void KeepHeld(List<ZDO> nearObjects)
		{
			if (held != null && Object.op_Implicit((Object)(object)heldView))
			{
				ZDO zDO = heldView.GetZDO();
				if (zDO != null)
				{
					nearObjects.Add(zDO);
				}
			}
		}
	}
	internal static class HostLink
	{
		private enum Op
		{
			Hello = 1,
			Teleport,
			Locations,
			Event,
			RandomEvent,
			StopEvent,
			Players,
			Message,
			SkipTime,
			GameRules
		}

		private const string RequestRpc = "AdminMenu_Request";

		private const string ReplyRpc = "AdminMenu_Reply";

		private static readonly FieldRef<ZNet, SyncedList> AdminList = AccessTools.FieldRefAccess<ZNet, SyncedList>("m_adminList");

		private static readonly Func<ZNet, SyncedList, string, bool> ListContainsId = AccessTools.MethodDelegate<Func<ZNet, SyncedList, string, bool>>(AccessTools.Method(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null), (object)null, true);

		private static ZRoutedRpc registered;

		private static int hellos;

		private static float nextHello;

		private static float locationsAsked = -100f;

		private static float helloAnsweredAt;

		internal static bool HostHasMenu;

		internal static readonly List<KeyValuePair<string, Vector3>> Locations = new List<KeyValuePair<string, Vector3>>();

		internal static int LocationsVersion;

		private const float Grace = 40f;

		private const float KickDelay = 5f;

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

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

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

		private static readonly Action<ZNet, ZNetPeer> InternalKick = AccessTools.MethodDelegate<Action<ZNet, ZNetPeer>>(AccessTools.Method(typeof(ZNet), "InternalKick", new Type[1] { typeof(ZNetPeer) }, (Type[])null), (object)null, true);

		private static float requiredSince = -1f;

		private static float nextCheck;

		internal static bool Client
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return !ZNet.instance.IsServer();
				}
				return false;
			}
		}

		internal static bool Relayed
		{
			get
			{
				if (Client)
				{
					return HostHasMenu;
				}
				return false;
			}
		}

		internal static void Update()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null)
			{
				registered = null;
				return;
			}
			if (instance != registered)
			{
				registered = instance;
				HostHasMenu = false;
				hellos = 0;
				nextHello = 0f;
				Locations.Clear();
				LocationsVersion = 0;
				WorldRules.ResetHostRules(Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer());
				instance.Register<ZPackage>("AdminMenu_Request", (Action<long, ZPackage>)OnRequest);
				instance.Register<ZPackage>("AdminMenu_Reply", (Action<long, ZPackage>)OnReply);
				PlayerLink.Register(instance);
			}
			if (Client && !HostHasMenu && hellos < 3 && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.unscaledTime > nextHello)
			{
				hellos++;
				nextHello = Time.unscaledTime + 10f;
				Send(Op.Hello, delegate(ZPackage p)
				{
					p.Write("0.9.6");
				});
			}
			if (WorldRules.HostRulesPending && Client && ((hellos >= 3 && Time.unscaledTime > nextHello) || (HostHasMenu && Time.unscaledTime > helloAnsweredAt + 5f)))
			{
				WorldRules.ResetHostRules(pending: false);
			}
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				CheckClients();
			}
			else if (clientVersions.Count > 0)
			{
				clientVersions.Clear();
			}
		}

		internal static string ClientVersion(long session)
		{
			if (!clientVersions.TryGetValue(session, out var value))
			{
				return null;
			}
			return value;
		}

		private static void CheckClients()
		{
			if (Time.unscaledTime < nextCheck)
			{
				return;
			}
			nextCheck = Time.unscaledTime + 1f;
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			HashSet<long> hashSet = new HashSet<long>();
			foreach (ZNetPeer item in peers)
			{
				hashSet.Add(item.m_uid);
			}
			Forget(clientVersions, hashSet);
			Forget(firstSeen, hashSet);
			Forget(kickAt, hashSet);
			if (!WorldRules.NeedModEverywhere)
			{
				requiredSince = -1f;
				kickAt.Clear();
				return;
			}
			if (requiredSince < 0f)
			{
				requiredSince = Time.unscaledTime;
			}
			foreach (ZNetPeer item2 in peers)
			{
				if (((ZDOID)(ref item2.m_characterID)).IsNone())
				{
					continue;
				}
				if (!firstSeen.ContainsKey(item2.m_uid))
				{
					firstSeen[item2.m_uid] = Time.unscaledTime;
				}
				if (kickAt.TryGetValue(item2.m_uid, out var value))
				{
					if (Time.unscaledTime >= value)
					{
						kickAt.Remove(item2.m_uid);
						Plugin.Log("kicking " + item2.m_playerName + ": AdminMenu " + (ClientVersion(item2.m_uid) ?? "missing"));
						InternalKick(ZNet.instance, item2);
					}
					continue;
				}
				string text = ClientVersion(item2.m_uid);
				bool flag = Time.unscaledTime - Mathf.Max(firstSeen[item2.m_uid], requiredSince) > 40f;
				if (!(text == "0.9.6") && (text != null || flag))
				{
					string text2 = ((text == null) ? L.Both("host.need_mod", "0.9.6") : L.Both("host.wrong_version", "0.9.6", text));
					ZRoutedRpc.instance.InvokeRoutedRPC(item2.m_uid, "ShowMessage", new object[2] { 2, text2 });
					kickAt[item2.m_uid] = Time.unscaledTime + 5f;
				}
			}
		}

		private static void Forget<T>(Dictionary<long, T> map, HashSet<long> here)
		{
			List<long> list = new List<long>();
			foreach (long key in map.Keys)
			{
				if (!here.Contains(key))
				{
					list.Add(key);
				}
			}
			foreach (long item in list)
			{
				map.Remove(item);
			}
		}

		internal static void SendGameRules(long to)
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || ZRoutedRpc.instance == null)
			{
				return;
			}
			Dictionary<string, string> rules = WorldRules.GameRulesToSend();
			List<long> list = new List<long>();
			if (to != 0L)
			{
				list.Add(to);
			}
			else
			{
				foreach (KeyValuePair<long, string> clientVersion in clientVersions)
				{
					if (L.KnowsKeys(clientVersion.Value))
					{
						list.Add(clientVersion.Key);
					}
				}
			}
			foreach (long item in list)
			{
				Reply(item, Op.GameRules, delegate(ZPackage p)
				{
					p.Write(rules.Count);
					foreach (KeyValuePair<string, string> item2 in rules)
					{
						p.Write(item2.Key);
						p.Write(item2.Value);
					}
				});
			}
		}

		internal static void DrawWaiting()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (WorldRules.HostRulesPending && Client && hellos != 0 && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				GUIContent val = new GUIContent(L.T("host.rules_waiting"));
				GUIStyle box = GUI.skin.box;
				Vector2 val2 = box.CalcSize(val);
				GUI.Box(new Rect(((float)Screen.width - val2.x - 24f) / 2f, 12f, val2.x + 24f, val2.y + 8f), val, box);
			}
		}

		internal static void AskAgain()
		{
			if (Client)
			{
				hellos = 0;
				nextHello = 0f;
				HostHasMenu = false;
				WorldRules.ResetHostRules(pending: true);
			}
		}

		internal static string Blocker()
		{
			if (!Terminal.m_cheat)
			{
				return L.T("block.cheats_off");
			}
			if (!AdminRights.IsClientAdmin)
			{
				return L.T("block.need_rights");
			}
			if (!HostHasMenu)
			{
				return L.T("host.server_lacks_mod");
			}
			if (!Achievements.IsCheatedAtAll())
			{
				return L.T("block.confirm_cheats");
			}
			return null;
		}

		internal static void Teleport(long who, ZDOID to)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Send(Op.Teleport, L.T("host.log_move"), delegate(ZPackage p)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				p.Write(who);
				p.Write(to);
			});
		}

		internal static void RequestLocations()
		{
			if (!(Time.unscaledTime - locationsAsked < 15f))
			{
				locationsAsked = Time.unscaledTime;
				Send(Op.Locations, null, null);
			}
		}

		internal static void StartEvent(string name)
		{
			Send(Op.Event, L.F("host.log_event", name), delegate(ZPackage p)
			{
				p.Write(name);
			});
		}

		internal static void RandomEvent()
		{
			Send(Op.RandomEvent, L.T("host.log_random_event"), null);
		}

		internal static void StopEvent()
		{
			Send(Op.StopEvent, L.T("host.log_stop_event"), null);
		}

		internal static void Players(int players)
		{
			Send(Op.Players, L.F("host.log_difficulty", players), delegate(ZPackage p)
			{
				p.Write(players);
			});
		}

		internal static void SkipTime(double seconds)
		{
			Send(Op.SkipTime, L.F("host.log_time", ((seconds >= 0.0) ? "+" : "") + Mathf.RoundToInt((float)seconds)), delegate(ZPackage p)
			{
				p.Write(seconds);
			});
		}

		private static void Send(Op op, Action<ZPackage> write)
		{
			Send(op, null, write);
		}

		private static void Send(Op op, string log, Action<ZPackage> write)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			ZNetPeer val = (Object.op_Implicit((Object)(object)ZNet.instance) ? ZNet.instance.GetServerPeer() : null);
			if (val != null && ZRoutedRpc.instance != null)
			{
				if (log != null)
				{
					Commands.AddLog("<color=#8a857c>» " + L.F("host.log_sent", log) + "</color>");
				}
				ZPackage val2 = new ZPackage();
				val2.Write((int)op);
				write?.Invoke(val2);
				ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "AdminMenu_Request", new object[1] { val2 });
			}
		}

		private static void Reply(long to, Op op, Action<ZPackage> write)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write((int)op);
			write?.Invoke(val);
			ZRoutedRpc.instance.InvokeRoutedRPC(to, "AdminMenu_Reply", new object[1] { val });
		}

		private static void Tell(long to, string key, params object[] args)
		{
			Reply(to, Op.Message, delegate(ZPackage p)
			{
				p.Write(L.ForVersion(ClientVersion(to), key, args));
			});
		}

		private static void OnRequest(long sender, ZPackage pkg)
		{
			//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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
				{
					return;
				}
				Op op = (Op)pkg.ReadInt();
				if (op == Op.Hello)
				{
					clientVersions[sender] = ((pkg.GetPos() < pkg.Size()) ? pkg.ReadString() : "0.1.0");
					Reply(sender, Op.Hello, null);
					if (L.KnowsKeys(clientVersions[sender]))
					{
						SendGameRules(sender);
					}
					return;
				}
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				SyncedList val = AdminList.Invoke(ZNet.instance);
				if (peer == null || val == null || !ListContainsId(ZNet.instance, val, peer.m_socket.GetHostName()))
				{
					Tell(sender, "host.no_rights");
					return;
				}
				switch (op)
				{
				case Op.Teleport:
				{
					long num2 = pkg.ReadLong();
					ZDOID val2 = pkg.ReadZDOID();
					if (num2 == ZNet.GetUID() && Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						Tell(sender, "host.no_move_host");
						break;
					}
					ZDO zDO = ZDOMan.instance.GetZDO(val2);
					if (zDO == null)
					{
						Tell(sender, "host.no_player");
						break;
					}
					ZRoutedRpc.instance.InvokeRoutedRPC(num2, "RPC_TeleportPlayer", new object[3]
					{
						zDO.GetPosition(),
						zDO.GetRotation(),
						true
					});
					Plugin.Log(peer.m_playerName + " teleports " + NameOf(num2) + " to " + NameOf(((ZDOID)(ref val2)).UserID));
					break;
				}
				case Op.Locations:
					Reply(sender, Op.Locations, WriteLocations);
					break;
				case Op.Event:
				{
					string text = pkg.ReadString();
					if (!Object.op_Implicit((Object)(object)RandEventSystem.instance) || !RandEventSystem.instance.HaveEvent(text))
					{
						Tell(sender, "host.no_event", text);
					}
					else
					{
						ZDO zDO2 = ZDOMan.instance.GetZDO(peer.m_characterID);
						RandEventSystem.instance.SetRandomEventByName(text, (zDO2 != null) ? zDO2.GetPosition() : peer.GetRefPos());
						Plugin.Log(peer.m_playerName + " starts event " + text);
					}
					break;
				}
				case Op.RandomEvent:
					if (Object.op_Implicit((Object)(object)RandEventSystem.instance))
					{
						RandEventSystem.instance.StartRandomEvent();
					}
					break;
				case Op.StopEvent:
					if (Object.op_Implicit((Object)(object)RandEventSystem.instance))
					{
						RandEventSystem.instance.ResetRandomEvent();
					}
					break;
				case Op.SkipTime:
				{
					double num3 = pkg.ReadDouble();
					ZNet.instance.SetNetTime(Math.Max(0.0, ZNet.instance.GetTimeSeconds() + num3));
					Plugin.Log(peer.m_playerName + " moves time by " + num3.ToString("0") + " s");
					break;
				}
				case Op.Players:
				{
					int num = pkg.ReadInt();
					if (Object.op_Implicit((Object)(object)Game.instance))
					{
						Game.instance.SetForcePlayerDifficulty(num);
					}
					Tell(sender, (num > 0) ? "host.difficulty_set" : "host.difficulty_auto", num);
					break;
				}
				case Op.Message:
					break;
				}
			}
			catch (Exception e)
			{
				Guard.Report("host request", e);
			}
		}

		private static void WriteLocations(ZPackage pkg)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_00b1: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			ZPackage val = new ZPackage();
			int num = 0;
			foreach (LocationInstance location in ZoneSystem.instance.GetLocationList())
			{
				string text = location.m_location?.m_prefab.Name;
				if (!string.IsNullOrEmpty(text))
				{
					if (!dictionary.TryGetValue(text, out var value))
					{
						value = (dictionary[text] = list.Count);
						list.Add(text);
					}
					val.Write(value);
					val.Write(location.m_position);
					num++;
				}
			}
			ZPackage val2 = new ZPackage();
			val2.Write(list.Count);
			foreach (string item in list)
			{
				val2.Write(item);
			}
			val2.Write(num);
			val2.Write(val);
			pkg.WriteCompressed(val2);
		}

		private static void OnReply(long sender, ZPackage pkg)
		{
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ZNetPeer val = (Object.op_Implicit((Object)(object)ZNet.instance) ? ZNet.instance.GetServerPeer() : null);
				if (val == null || sender != val.m_uid)
				{
					return;
				}
				switch ((Op)pkg.ReadInt())
				{
				case Op.Hello:
					HostHasMenu = true;
					helloAnsweredAt = Time.unscaledTime;
					break;
				case Op.GameRules:
				{
					Dictionary<string, string> dictionary = new Dictionary<string, string>();
					for (int num3 = pkg.ReadInt(); num3 > 0; num3--)
					{
						dictionary[pkg.ReadString()] = pkg.ReadString();
					}
					bool hostRulesPending = WorldRules.HostRulesPending;
					WorldRules.SetHostRules(dictionary);
					int num4 = WorldRules.CountOf(dictionary);
					if (hostRulesPending && num4 > 0 && Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						((Character)Player.m_localPlayer).Message((MessageType)1, L.F("host.rules_received", num4), 0, (Sprite)null, false);
					}
					break;
				}
				case Op.Message:
					Commands.AddLog("<color=#e0a040>" + L.Decode(pkg.ReadString()) + "</color>");
					break;
				case Op.Locations:
				{
					ZPackage val2 = pkg.ReadCompressedPackage();
					string[] array = new string[val2.ReadInt()];
					for (int i = 0; i < array.Length; i++)
					{
						array[i] = val2.ReadString();
					}
					int num = val2.ReadInt();
					ZPackage val3 = val2.ReadPackage();
					Locations.Clear();
					for (int j = 0; j < num; j++)
					{
						int num2 = val3.ReadInt();
						Locations.Add(new KeyValuePair<string, Vector3>(array[num2], val3.ReadVector3()));
					}
					LocationsVersion++;
					break;
				}
				}
			}
			catch (Exception e)
			{
				Guard.Report("host reply", e);
			}
		}

		private static string NameOf(long session)
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				ZDOID characterID = player.m_characterID;
				if (((ZDOID)(ref characterID)).UserID == session)
				{
					return player.m_name;
				}
			}
			return session.ToString();
		}
	}
	internal static class InputBlocker
	{
		private static GameObject root;

		private static RectTransform panelArea;

		private static RectTransform tabArea;

		private static RectTransform windowArea;

		internal static void Cover(Rect panel, Rect tab, Rect window = default(Rect))
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)root))
			{
				Create();
			}
			if (!root.activeSelf)
			{
				root.SetActive(true);
			}
			Place(panelArea, panel);
			Place(tabArea, tab);
			Place(windowArea, window);
		}

		internal static void Hide()
		{
			if (Object.op_Implicit((Object)(object)root) && root.activeSelf)
			{
				root.SetActive(false);
			}
		}

		internal static void Remove()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)root);
			}
		}

		private static void Place(RectTransform area, Rect guiRect)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			area.anchoredPosition = new Vector2(((Rect)(ref guiRect)).x, (float)Screen.height - ((Rect)(ref guiRect)).yMax);
			area.sizeDelta = ((Rect)(ref guiRect)).size;
		}

		private static void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			root = new GameObject("AdminMenu.InputBlocker");
			Object.DontDestroyOnLoad((Object)(object)root);
			Canvas obj = root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32000;
			root.AddComponent<GraphicRaycaster>();
			panelArea = AddArea("Panel");
			tabArea = AddArea("Tab");
			windowArea = AddArea("Window");
		}

		private static RectTransform AddArea(string name)
		{
			//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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(root.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = (val2.pivot = Vector2.zero);
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			Image obj = val.AddComponent<Image>();
			((Graphic)obj).color = Color.clear;
			((Graphic)obj).canvasRenderer.cullTransparentMesh = true;
			return val2;
		}
	}
	public enum LanguageMode
	{
		Auto,
		English,
		Russian
	}
	internal static class L
	{
		private static Dictionary<string, string[]> table;

		private static readonly HashSet<string> reported = new HashSet<string>();

		internal static Action<string> Missing;

		private const char WireMark = '\u0001';

		private const char WireArg = '\u0002';

		internal static bool Russian { get; private set; }

		internal static int Generation { get; private set; } = 1;

		internal static IEnumerable<string> Keys => Table.Keys;

		private static Dictionary<string, string[]> Table
		{
			get
			{
				if (table != null)
				{
					return table;
				}
				Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>(StringComparer.Ordinal);
				for (int i = 0; i < Strings.Entries.GetLength(0); i++)
				{
					dictionary[Strings.Entries[i, 0]] = new string[2]
					{
						Strings.Entries[i, 1],
						Strings.Entries[i, 2]
					};
				}
				return table = dictionary;
			}
		}

		internal static void Set(LanguageMode mode, string gameLanguage)
		{
			bool flag = mode switch
			{
				LanguageMode.Auto => string.Equals(gameLanguage, "Russian", StringComparison.OrdinalIgnoreCase), 
				LanguageMode.Russian => true, 
				_ => false, 
			};
			if (flag != Russian)
			{
				Russian = flag;
				Generation++;
			}
		}

		internal static string T(string key)
		{
			return Text(key, Russian);
		}

		internal static string Ru(string key)
		{
			return Text(key, russian: true);
		}

		internal static string En(string key)
		{
			return Text(key, russian: false);
		}

		internal static string F(string key, params object[] args)
		{
			return Format(T(key), args);
		}

		internal static string N(string key, long n)
		{
			return Plural(T(key), n, Russian);
		}

		internal static string Both(string key, params object[] args)
		{
			return Format(En(key), args) + "\n" + Format(Ru(key), args);
		}

		internal static string Wire(string key, params object[] args)
		{
			StringBuilder stringBuilder = new StringBuilder().Append('\u0001').Append(key);
			foreach (object obj in args)
			{
				stringBuilder.Append('\u0002').Append(Convert.ToString(obj, CultureInfo.InvariantCulture));
			}
			return stringBuilder.ToString();
		}

		internal static string Decode(string text)
		{
			if (string.IsNullOrEmpty(text) || text[0] != '\u0001')
			{
				return text;
			}
			string[] array = text.Substring(1).Split('\u0002');
			if (!Table.ContainsKey(array[0]))
			{
				return string.Join(" ", array);
			}
			object[] array2 = new object[array.Length - 1];
			Array.Copy(array, 1, array2, 0, array2.Length);
			return F(array[0], array2);
		}

		internal static bool KnowsKeys(string version)
		{
			if (version != null && Version.TryParse(version, out Version result))
			{
				return result >= new Version(0, 4, 0);
			}
			return false;
		}

		internal static string ForVersion(string version, string key, params object[] args)
		{
			if (!KnowsKeys(version))
			{
				return Format(Ru(key), args);
			}
			return Wire(key, args);
		}

		private static string Text(string key, bool russian)
		{
			if (key != null && Table.TryGetValue(key, out var value))
			{
				return value[(!russian) ? 1u : 0u];
			}
			if (reported.Add(key ?? ""))
			{
				Missing?.Invoke("no text for key " + key);
			}
			return key ?? "";
		}

		private static string Format(string text, object[] args)
		{
			if (args != null && args.Length != 0)
			{
				return string.Format(CultureInfo.InvariantCulture, text, args);
			}
			return text;
		}

		internal static string Plural(string forms, long n, bool russian)
		{
			string[] array = forms.Split('|');
			long num = Math.Abs(n) % 10;
			long num2 = Math.Abs(n) % 100;
			int val = ((!russian) ? ((n != 1) ? 1 : 0) : ((num != 1 || num2 == 11) ? ((num >= 2 && num <= 4 && (num2 < 12 || num2 > 14)) ? 1 : 2) : 0));
			return array[Math.Min(val, array.Length - 1)];
		}
	}
	internal static class LocationFinder
	{
		internal sealed class Kind
		{
			internal string Key;

			internal string Category;

			internal string Name;

			internal string Note;

			internal PinType Icon;

			internal readonly List<string> PrefabNames = new List<string>();

			internal readonly List<Vector3> Places = new List<Vector3>();

			internal readonly List<PinData> Pins = new List<PinData>();

			internal readonly List<string> Sometimes = new List<string>();

			internal readonly List<string> InRooms = new List<string>();

			internal bool Marked;

			internal float Nearest = float.MaxValue;

			internal Vector3 NearestPlace;

			internal int InRadius;
		}

		internal const string Bosses = "loc.bosses";

		internal const string Hints = "loc.hints";

		internal const string Dungeons = "loc.dungeons";

		internal const string Camps = "loc.camps";

		internal const string Lore = "loc.lore";

		internal const string Traders = "loc.traders";

		internal const string Other = "loc.other";

		internal const string Prefabs = "loc.prefabs";

		internal static readonly string[] Categories = new string[8] { "loc.bosses", "loc.hints", "loc.dungeons", "loc.camps", "loc.lore", "loc.traders", "loc.other", "loc.prefabs" };

		private const int MaxPinsPerKind = 300;

		private const PinType BossPin = (PinType)9;

		private const PinType HintPin = (PinType)6;

		private const PinType PlacePin = (PinType)3;

		private const PinType HousePin = (PinType)1;

		private static readonly Dictionary<string, string> CampNames = new Dictionary<string, string>
		{
			{ "WoodVillage1", "loc.draugr_village" },
			{ "WoodVillage2", "loc.draugr_village" },
			{ "GoblinCamp2", "loc.fuling_camp" },
			{ "Greydwarf_camp1", "loc.greydwarf_camp" },
			{ "FortressRuins", "loc.fortress_ruins" },
			{ "AshlandRuins", "loc.ashlands_ruins" },
			{ "CharredFortress", "$charredfortress" },
			{ "NorthVillage", "loc.north_village" },
			{ "HalfBurried_ForestCrypt", "loc.half_buried_crypt" }
		};

		private static readonly Dictionary<string, string> TraderNames = new Dictionary<string, string> { { "BogWitch_Camp", "$npc_bogwitch" } };

		internal static readonly List<Kind> Kinds = new List<Kind>();

		internal static float Radius = 1000f;

		internal static string Summary = "";

		internal static bool Wanted;

		private static ZoneSystem indexed;

		private static int indexedCount = -1;

		private static int builtVersion = -1;

		private static int builtLanguage;

		private static Minimap pinsOn;

		private static float measuredAt = -10f;

		private static float radiusChangedAt = -10f;

		private static bool remarkPending;

		internal static string Unavailable()
		{
			if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return L.T("common.world_not_loaded");
			}
			if (HostLink.Client)
			{
				return HostLink.Blocker() ?? Commands.Blocker("find");
			}
			return Commands.Blocker("find");
		}

		internal static void Update()
		{
			if (Wanted && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Unavailable() == null)
			{
				if (pinsOn != Minimap.instance)
				{
					ForgetPins();
				}
				LocationScanner.Update();
				ZoneSystem instance = ZoneSystem.instance;
				if (HostLink.Client && HostLink.LocationsVersion == 0)
				{
					HostLink.RequestLocations();
				}
				int num = (HostLink.Client ? HostLink.LocationsVersion : instance.GetLocationList().Count);
				if (instance != indexed || num != indexedCount || LocationScanner.Version != builtVersion || L.Generation != builtLanguage)
				{
					Rebuild(instance, num);
				}
				if (remarkPending && Time.unscaledTime - radiusChangedAt > 0.35f && !ZInput.GetMouseButton(0))
				{
					remarkPending = false;
					MarkAll();
				}
				if (Time.unscaledTime - measuredAt > 0.5f)
				{
					Measure();
				}
			}
		}

		internal static void Forget()
		{
			builtVersion = int.MinValue;
		}

		internal static void SetRadius(float radius)
		{
			radius = Mathf.Max(1f, radius);
			if (!Mathf.Approximately(radius, Radius))
			{
				Radius = radius;
				radiusChangedAt = Time.unscaledTime;
				remarkPending = true;
				measuredAt = -10f;
			}
		}

		internal static void Toggle(Kind kind)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			kind.Marked