Decompiled source of MinePortal v0.10.0

plugins/MinePortal.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Sansara.Chronicle;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("MinePortal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.10.0.0")]
[assembly: AssemblyInformationalVersion("0.10.0+faa5470458e997864ff36b12322138ba2e82b128")]
[assembly: AssemblyProduct("MinePortal")]
[assembly: AssemblyTitle("MinePortal")]
[assembly: AssemblyVersion("0.10.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 Sansara.Chronicle
{
	public sealed class ChroniclePlayer
	{
		public long Id { get; }

		public string Name { get; }

		public ChroniclePlayer(long id, string name)
		{
			Id = id;
			Name = name ?? "";
		}
	}
	public sealed class ChronicleEntry
	{
		public double Time;

		public string Date = "";

		public string Kind = "";

		public string Id = "";

		public string Result = "";

		public List<ChroniclePlayer> Players = new List<ChroniclePlayer>();

		public const string Victory = "victory";

		public bool IsVictory
		{
			get
			{
				if (!(Result == "victory"))
				{
					return Result == "found";
				}
				return true;
			}
		}

		public static string Clean(string s)
		{
			return new string((s ?? "").Where((char c) => c != '\t' && c != '\n' && c != '\r' && c != '|' && c != '=').ToArray()).Trim();
		}

		public string ToLine()
		{
			string text = string.Join("|", Players.Select((ChroniclePlayer p) => p.Id.ToString(CultureInfo.InvariantCulture) + "=" + Clean(p.Name)));
			return string.Join("\t", Time.ToString("R", CultureInfo.InvariantCulture), Clean(Date), Clean(Kind), Clean(Id), Clean(Result), text);
		}

		public static ChronicleEntry Parse(string line)
		{
			if (string.IsNullOrWhiteSpace(line) || line.TrimStart(Array.Empty<char>()).StartsWith("#", StringComparison.Ordinal))
			{
				return null;
			}
			string[] array = line.TrimEnd(new char[1] { '\r' }).Split(new char[1] { '\t' });
			if (array.Length < 5 || !double.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || array[2].Trim() == "" || array[3].Trim() == "")
			{
				return null;
			}
			ChronicleEntry chronicleEntry = new ChronicleEntry
			{
				Time = result,
				Date = array[1].Trim(),
				Kind = array[2].Trim(),
				Id = array[3].Trim(),
				Result = array[4].Trim()
			};
			if (array.Length > 5)
			{
				string[] array2 = array[5].Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text in array2)
				{
					int num = text.IndexOf('=');
					long.TryParse((num > 0) ? text.Substring(0, num) : "0", NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2);
					chronicleEntry.Players.Add(new ChroniclePlayer(result2, (num >= 0) ? text.Substring(num + 1) : text));
				}
			}
			return chronicleEntry;
		}

		public static List<ChronicleEntry> ParseAll(string text, out int bad)
		{
			List<ChronicleEntry> list = new List<ChronicleEntry>();
			bad = 0;
			string[] array = (text ?? "").Split(new char[1] { '\n' });
			foreach (string text2 in array)
			{
				ChronicleEntry chronicleEntry = Parse(text2);
				if (chronicleEntry != null)
				{
					list.Add(chronicleEntry);
				}
				else if (!string.IsNullOrWhiteSpace(text2) && !text2.TrimStart(Array.Empty<char>()).StartsWith("#", StringComparison.Ordinal))
				{
					bad++;
				}
			}
			return list;
		}
	}
	public static class ChronicleFile
	{
		public static string PathFor(string configDir, string world)
		{
			string text = string.Concat((world ?? "world").Split(Path.GetInvalidFileNameChars()));
			return Path.Combine(configDir, "sansara.Chronicle", text + ".tsv");
		}

		public static void Append(string path, ChronicleEntry entry)
		{
			Directory.CreateDirectory(Path.GetDirectoryName(path));
			File.AppendAllText(path, entry.ToLine() + "\n", new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
		}

		public static List<ChronicleEntry> Read(string path, out int bad)
		{
			bad = 0;
			if (!File.Exists(path))
			{
				return new List<ChronicleEntry>();
			}
			return ChronicleEntry.ParseAll(File.ReadAllText(path), out bad);
		}
	}
	public sealed class FirstVictory
	{
		public string Id;

		public string Date;

		public List<string> Names = new List<string>();

		public int Count;
	}
	public sealed class Leader
	{
		public string Name;

		public int Count;
	}
	public static class ChronicleStats
	{
		public static Dictionary<string, FirstVictory> Firsts(IEnumerable<ChronicleEntry> all, string kind)
		{
			Dictionary<string, FirstVictory> dictionary = new Dictionary<string, FirstVictory>();
			foreach (ChronicleEntry item in from e in all
				where e.Kind == kind && e.IsVictory
				orderby e.Time
				select e)
			{
				if (!dictionary.TryGetValue(item.Id, out var value))
				{
					value = new FirstVictory
					{
						Id = item.Id,
						Date = item.Date,
						Names = (from p in item.Players
							select p.Name into n
							where n != ""
							select n).Distinct().ToList()
					};
					dictionary[item.Id] = value;
				}
				value.Count++;
			}
			return dictionary;
		}

		public static List<Leader> Leaders(IEnumerable<ChronicleEntry> all, string kind)
		{
			Dictionary<long, int> dictionary = new Dictionary<long, int>();
			Dictionary<long, string> names = new Dictionary<long, string>();
			foreach (ChronicleEntry item in from e in all
				where e.Kind == kind && e.IsVictory
				orderby e.Time
				select e)
			{
				foreach (ChroniclePlayer item2 in from p in item.Players
					group p by (p.Id == 0L) ? p.Name : p.Id.ToString() into g
					select g.First())
				{
					long key = ((item2.Id != 0L) ? item2.Id : item2.Name.GetHashCode());
					dictionary[key] = ((!dictionary.TryGetValue(key, out var value)) ? 1 : (value + 1));
					if (item2.Name != "")
					{
						names[key] = item2.Name;
					}
				}
			}
			string value2;
			return (from kv in dictionary
				select new Leader
				{
					Name = (names.TryGetValue(kv.Key, out value2) ? value2 : "?"),
					Count = kv.Value
				} into l
				orderby l.Count descending
				select l).ThenBy<Leader, string>((Leader l) => l.Name, StringComparer.Ordinal).ToList();
		}

		public static string Names(IList<string> names, int max)
		{
			if (names.Count == 0)
			{
				return "";
			}
			for (int num = names.Count; num >= 1; num--)
			{
				string text = string.Join(", ", names.Take(num)) + ((num < names.Count) ? $" +{names.Count - num}" : "");
				if (text.Length <= max)
				{
					return text;
				}
			}
			string text2 = names[0];
			if (text2.Length <= max)
			{
				return text2;
			}
			return text2.Substring(0, Math.Max(1, max - 1)) + "…";
		}
	}
}
namespace MinePortal
{
	internal static class Mines
	{
		private enum PrefabKind
		{
			Other,
			Creature,
			Spawner,
			Nest
		}

		internal const string TagPrefix = "Испытание";

		private const string CollapsedTag = "Испытание обрушилось";

		private const float ResetWaitSeconds = 30f;

		private const float PresenceSaveSeconds = 60f;

		private static readonly Dictionary<int, bool> Tombstones = new Dictionary<int, bool>();

		private static readonly Dictionary<int, bool> Pieces = new Dictionary<int, bool>();

		private static readonly Dictionary<Vector2s, List<Vector2s>> Wiped = new Dictionary<Vector2s, List<Vector2s>>();

		private static float _lastPresenceSave;

		private const float InteriorMinY = 3000f;

		private const float ReturnTimeout = 20f;

		private static readonly int TypeKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.type");

		private static readonly int ZoneXKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.zoneX");

		private static readonly int ZoneYKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.zoneY");

		private static readonly int CenterKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.center");

		private static readonly int InnerKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.inner");

		private static readonly int LegacySlotKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.slot");

		private static readonly int PopulatedKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.populated");

		private static readonly int ClearedKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.cleared");

		private static readonly int MembersKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.members");

		private static readonly int RewardedKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.rewarded");

		private static readonly int GivenKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.given");

		private static readonly int VisitedKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.visited");

		private static readonly int ReadyAtKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.readyAt");

		private static readonly int LastPresenceKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.lastPresence");

		private static readonly int VisitorsKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.visitors");

		private static readonly int SpawnedKey = StringExtensionMethods.GetStableHashCode("sansara.MinePortal.spawned");

		private static readonly Dictionary<Vector2s, MineRun> Runs = new Dictionary<Vector2s, MineRun>();

		private static MethodInfo _spawnZone;

		private static MethodInfo _isZoneGenerated;

		private static FieldInfo _objectsBySector;

		private static FieldInfo _simulationDistance;

		public static bool Started;

		private const float RoomMargin = 24f;

		private const float LairFloorOffset = -1.6f;

		private const float SturdyHealth = 10000000f;

		private static FieldInfo _ewpSkip;

		private static bool _ewpChecked;

		private static readonly Dictionary<int, PrefabKind> Kinds = new Dictionary<int, PrefabKind>();

		private const float HintSeconds = 5f;

		private const float StallSeconds = 120f;

		private static MethodInfo _enqueueReward;

		private static bool _rewardApiChecked;

		private static readonly Random Rng = new Random();

		private static List<string> _tombstonePrefabs;

		private static FieldInfo EwpSkip
		{
			get
			{
				if (!_ewpChecked)
				{
					_ewpChecked = true;
					Type type = AccessTools.TypeByName("ExpandWorld.Prefab.HandleCreated");
					_ewpSkip = ((type == null) ? null : AccessTools.Field(type, "Skip"));
					Plugin.Log.LogInfo((object)((_ewpSkip != null) ? "Expand World Prefabs найден: объекты испытаний не проходят его правила create." : "Expand World Prefabs не найден (или изменился) — флаг пропуска не используется."));
				}
				return _ewpSkip;
			}
		}

		internal static long Now()
		{
			return (long)ZNet.instance.GetTimeSeconds();
		}

		private static void MarkPresence(MineRun run, bool entered)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			run.LastPresence = Now();
			ZDO zDO = ZDOMan.instance.GetZDO(run.Origin);
			if (entered && !run.Visited)
			{
				run.Visited = true;
				if (zDO != null)
				{
					zDO.Set(VisitedKey, 1, false);
				}
			}
			if (zDO != null)
			{
				zDO.Set(LastPresenceKey, run.LastPresence);
			}
		}

		private static void CheckTimeouts(MineRun run)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (run.Stage != Stage.Ready)
			{
				return;
			}
			if (run.Inside.Count > 0 || run.Returning.Count > 0)
			{
				run.LastPresence = Now();
				if (Time.time - _lastPresenceSave > 60f)
				{
					_lastPresenceSave = Time.time;
					ZDO zDO = ZDOMan.instance.GetZDO(run.Origin);
					if (zDO != null)
					{
						zDO.Set(LastPresenceKey, run.LastPresence);
					}
				}
			}
			else
			{
				long num = Now();
				if (ZDOMan.instance.GetZDO(run.Origin) == null)
				{
					Collapse(run, "исходный портал разрушен");
				}
				else if (!run.Visited && Plugin.IdleMinutes.Value > 0 && num - run.ReadyAt > (long)Plugin.IdleMinutes.Value * 60L)
				{
					Collapse(run, $"никто не вошёл за {Plugin.IdleMinutes.Value} мин");
				}
				else if (run.Visited && !run.Cleared && Plugin.AbandonMinutes.Value > 0 && num - run.LastPresence > (long)Plugin.AbandonMinutes.Value * 60L)
				{
					Collapse(run, $"брошено незачищенным: внутри никого {Plugin.AbandonMinutes.Value} мин");
				}
			}
		}

		private static void Collapse(MineRun run, string reason)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = (((ZDOID)(ref run.Inner)).IsNone() ? null : ZDOMan.instance.GetZDO(run.Inner));
			if (val != null)
			{
				Destroy(val);
			}
			ZDO val2 = (((ZDOID)(ref run.Origin)).IsNone() ? null : ZDOMan.instance.GetZDO(run.Origin));
			if (val2 != null)
			{
				RetirePortal(val2, run.Type.Title + ": " + reason);
			}
			run.Stage = Stage.Closing;
			Plugin.Log.LogInfo((object)(run.Name + ": обрушено (" + reason + "); место будет очищено, когда рядом никого не будет."));
		}

		private static void RetirePortal(ZDO portal, string reason)
		{
			//IL_000d: 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_0055: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			portal.SetOwner(ZDOMan.GetSessionID());
			portal.SetConnection((ConnectionType)1, ZDOID.None);
			portal.Set(ZDOVars.s_tag, "Испытание обрушилось");
			portal.Set(TypeKey, "");
			portal.Set(LegacySlotKey, -1, false);
			ZDOMan.instance.ForceSendZDO(portal.m_uid);
			NotifyNear(portal.GetPosition(), "Испытание обрушилось: " + reason + ".");
			Plugin.Log.LogInfo((object)$"Портал {portal.m_uid} у {portal.GetPosition()} отвязан и переименован: {reason}.");
		}

		private static void NotifyNear(Vector3 pos, string text)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZDO val = (((ZDOID)(ref peer.m_characterID)).IsNone() ? null : ZDOMan.instance.GetZDO(peer.m_characterID));
				if (val != null && Vector3.Distance(val.GetPosition(), pos) < 50f)
				{
					Message(peer.m_uid, text);
				}
			}
		}

		private static bool AnyPlayerInBlock(Vector2s slot)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZDO val = (((ZDOID)(ref peer.m_characterID)).IsNone() ? null : ZDOMan.instance.GetZDO(peer.m_characterID));
				if (val != null && Pool.InBlock(slot, val.GetPosition()))
				{
					return true;
				}
			}
			return false;
		}

		private static void TryReset(MineRun run)
		{
			//IL_000f: 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)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			if (run.Returning.Count > 0 || AnyPlayerInBlock(run.Zone))
			{
				return;
			}
			List<Vector2s> list = new List<Vector2s>();
			int num = 0;
			int num2 = 0;
			foreach (Vector2s item in Pool.BlockZones(run.Zone))
			{
				bool flag = item == run.Zone;
				bool flag2 = Mathf.Abs(item.x - run.Zone.x) <= 1 && Mathf.Abs(item.y - run.Zone.y) <= 1;
				if (!flag && !IsZoneGenerated(item))
				{
					if (!flag2)
					{
						continue;
					}
					foreach (ZDO item2 in from z in ZoneObjects(item)
						where z.GetPosition().y >= 3000f && !IsPlayer(z.GetPrefab()) && !IsTombstone(z.GetPrefab())
						select z)
					{
						Destroy(item2);
						num++;
					}
					continue;
				}
				List<ZDO> list2 = ZoneObjects(item);
				if (!flag && list2.Any((ZDO z) => IsPlayerPiece(z) && z.GetPosition().y < 3000f))
				{
					Plugin.Log.LogWarning((object)$"{run.Name}: в зоне блока {item} есть постройки игроков — зона не очищается.");
					continue;
				}
				List<ZDO> list3 = list2.Where((ZDO z) => IsTombstone(z.GetPrefab())).ToList();
				if (list3.Count > 0 && !run.HasHome)
				{
					Plugin.Log.LogWarning((object)$"{run.Name}: в зоне {item} {list3.Count} надгробий, а точка возврата неизвестна — зона не очищается.");
					if (flag)
					{
						run.Stage = Stage.Failed;
						Plugin.Log.LogWarning((object)(run.Name + ": место остаётся занятым. Разобрать вручную."));
						return;
					}
					continue;
				}
				foreach (ZDO item3 in list2)
				{
					if (IsTombstone(item3.GetPrefab()))
					{
						Vector2 val = Random.insideUnitCircle * 2f;
						MoveTombstone(item3, run.Home + run.HomeRot * Vector3.forward * 2f + new Vector3(val.x, 0.5f, val.y));
						num2++;
					}
					else if (!IsPlayer(item3.GetPrefab()))
					{
						Destroy(item3);
						num++;
					}
				}
				list.Add(item);
			}
			Wiped[run.Zone] = list;
			run.Stage = Stage.Resetting;
			run.ResetStartedAt = Time.time;
			Plugin.Log.LogInfo((object)$"{run.Name}: очистка блока: зон {list.Count}, удалено объектов {num}, перенесено к порталу надгробий {num2}.");
		}

		private static void CompleteReset(MineRun run)
		{
			//IL_0006: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2s> value;
			List<Vector2s> list = (Wiped.TryGetValue(run.Zone, out value) ? value : new List<Vector2s> { run.Zone });
			List<ZDO> list2 = (from z in list.SelectMany(ZoneObjects)
				where !IsPlayer(z.GetPrefab()) && !IsTombstone(z.GetPrefab())
				select z).ToList();
			if (list2.Count > 0 && Time.time - run.ResetStartedAt < 30f)
			{
				foreach (ZDO item in list2)
				{
					Destroy(item);
				}
				return;
			}
			if (list2.Count > 0)
			{
				string arg = string.Join(", ", from g in list2.GroupBy(delegate(ZDO z)
					{
						GameObject prefab = ZNetScene.instance.GetPrefab(z.GetPrefab());
						return ((prefab != null) ? ((Object)prefab).name : null) ?? z.GetPrefab().ToString();
					})
					select $"{g.Key} ×{g.Count()}");
				Plugin.Log.LogWarning((object)$"{run.Name}: после очистки осталось объектов {list2.Count}: {arg}.");
			}
			foreach (Vector2s item2 in list)
			{
				Unregister(item2, run.Type.Location.Value);
			}
			if (!list.Contains(run.Zone))
			{
				Unregister(run.Zone, run.Type.Location.Value);
			}
			Wiped.Remove(run.Zone);
			Runs.Remove(run.Zone);
			RescueTombstones();
			Registry.Remove(run.Zone);
			Plugin.Log.LogInfo((object)(run.Name + ": место очищено и свободно."));
		}

		private static void Unregister(Vector2s zone, string ourLocation)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			((HashSet<Vector2s>)AccessTools.Field(typeof(ZoneSystem), "m_generatedZones").GetValue(ZoneSystem.instance)).Remove(zone);
			ZoneSystem instance = ZoneSystem.instance;
			if (!instance.m_locationInstances.TryGetValue(zone, out var value))
			{
				return;
			}
			if (value.m_location?.m_prefab.Name != ourLocation)
			{
				value.m_placed = false;
				instance.m_locationInstances[zone] = value;
				return;
			}
			instance.m_locationInstances.Remove(zone);
			foreach (List<LocationInstance> value2 in instance.m_locationIDCache.Values)
			{
				value2.RemoveAll((LocationInstance l) => ZoneSystem.GetZone(l.m_position) == zone);
			}
			foreach (List<LocationInstance> item in instance.m_locationGroupCache.Values.Concat(instance.m_locationMaxGroupCache.Values))
			{
				item.RemoveAll((LocationInstance l) => ZoneSystem.GetZone(l.m_position) == zone);
			}
		}

		public static void SweepOrphans()
		{
			//IL_002d: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<Vector2s, string> entry in Registry.All)
			{
				if (!Runs.ContainsKey(entry.Key))
				{
					MineType mineType = Plugin.Types.FirstOrDefault((MineType t) => t.Id == entry.Value);
					if (mineType == null)
					{
						Plugin.Log.LogWarning((object)$"Место {entry.Key}: неизвестный вид испытания {entry.Value} — не трогаю.");
						continue;
					}
					Runs[entry.Key] = new MineRun
					{
						Type = mineType,
						Zone = entry.Key,
						Orphan = true,
						Stage = Stage.Closing
					};
					Plugin.Log.LogInfo((object)$"{mineType.Title}: на месте {entry.Key} брошенное испытание без портала — будет очищено.");
				}
			}
		}

		private static bool IsTombstone(int hash)
		{
			if (!Tombstones.TryGetValue(hash, out var value))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(hash);
				value = (Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TombStone>() != (Object)null;
				Tombstones[hash] = value;
			}
			return value;
		}

		private static bool IsPlayerPiece(ZDO zdo)
		{
			int prefab = zdo.GetPrefab();
			if (!Pieces.TryGetValue(prefab, out var value))
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				value = (Object)(object)prefab2 != (Object)null && (Object)(object)prefab2.GetComponent<Piece>() != (Object)null;
				Pieces[prefab] = value;
			}
			if (value)
			{
				return zdo.GetLong(ZDOVars.s_creator, 0L) != 0;
			}
			return false;
		}

		private static bool IsPlayer(int hash)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(hash);
			if ((Object)(object)prefab != (Object)null)
			{
				return (Object)(object)prefab.GetComponent<Player>() != (Object)null;
			}
			return false;
		}

		public static bool Init()
		{
			_spawnZone = AccessTools.Method(typeof(ZoneSystem), "SpawnZone", new Type[3]
			{
				typeof(Vector2s),
				typeof(SpawnMode),
				typeof(GameObject).MakeByRefType()
			}, (Type[])null);
			_isZoneGenerated = AccessTools.Method(typeof(ZoneSystem), "IsZoneGenerated", new Type[1] { typeof(Vector2s) }, (Type[])null);
			_objectsBySector = AccessTools.Field(typeof(ZDOMan), "m_objectsBySector");
			_simulationDistance = AccessTools.Field(typeof(ZoneSystem), "m_simulationDistance");
			if (_spawnZone != null && _isZoneGenerated != null)
			{
				return _objectsBySector != null;
			}
			return false;
		}

		public static void CheckBlockRadius()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			int num;
			if (!(_simulationDistance != null))
			{
				num = -1;
			}
			else
			{
				SimulationDistance val = (SimulationDistance)_simulationDistance.GetValue(ZoneSystem.instance);
				num = ((SimulationDistance)(ref val)).TotalSimulationDistance;
			}
			int num2 = num;
			if (num2 > Pool.BlockRadius)
			{
				Plugin.Log.LogWarning((object)$"Сервер строит зоны на {num2} вокруг игроков, а блок места — {Pool.BlockRadius}: увеличьте SlotSpacingZones до {2 * num2 + 2} и больше.");
			}
			else
			{
				Plugin.Log.LogInfo((object)$"Радиус постройки зон вокруг игроков {num2}, блок места {Pool.BlockRadius}.");
			}
		}

		private static MineType TypeOfTag(string tag)
		{
			return Plugin.Types.FirstOrDefault((MineType t) => t.IsKeyTag(tag));
		}

		public static void ScanKeyPortals()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			Vector2s val2 = default(Vector2s);
			foreach (ZDO portal in ZDOMan.instance.GetPortalList())
			{
				Vector3 position = portal.GetPosition();
				if (portal.GetInt(InnerKey, -1) >= 0 || position.y >= 3000f)
				{
					continue;
				}
				Vector2 val = new Vector2(position.x, position.z);
				if (((Vector2)(ref val)).magnitude > 10000f)
				{
					continue;
				}
				string text = portal.GetString(TypeKey, "");
				if (text != "")
				{
					((Vector2s)(ref val2))..ctor(portal.GetInt(ZoneXKey, 0), portal.GetInt(ZoneYKey, 0));
					if (!Runs.ContainsKey(val2))
					{
						Restore(portal, text, val2);
					}
				}
				else if (portal.GetInt(LegacySlotKey, -1) >= 0)
				{
					RetirePortal(portal, "портал старой версии мода");
				}
				else
				{
					MineType mineType = TypeOfTag(portal.GetString(ZDOVars.s_tag, ""));
					if (mineType != null)
					{
						Start(mineType, portal);
					}
				}
			}
		}

		private static void Start(MineType type, ZDO origin)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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)
			if (!FindFreeSlot(type, out var zone))
			{
				Plugin.Log.LogWarning((object)(type.Title + ": нет свободных мест пула; портал оставлен как есть."));
				return;
			}
			Vector3 zonePos = ZoneSystem.GetZonePos(zone);
			PurgeInteriorLeftovers(type, zone);
			PrepareVisited(type, zone);
			Vector3 val = default(Vector3);
			if (!ZoneSystem.instance.SpawnLocationMidGame(type.Location.Value, zonePos, ref val))
			{
				Plugin.Log.LogError((object)$"{type.Title}: не удалось зарегистрировать локацию {type.Location.Value} в {zonePos}.");
				return;
			}
			origin.SetOwner(ZDOMan.GetSessionID());
			origin.Set(ZDOVars.s_tag, string.Format("{0}: {1}·{2},{3}", "Испытание", type.KeyTag.Value, zone.x, zone.y));
			origin.Set(TypeKey, type.Id);
			origin.Set(ZoneXKey, (int)zone.x, false);
			origin.Set(ZoneYKey, (int)zone.y, false);
			origin.SetConnection((ConnectionType)1, ZDOID.None);
			ZDOMan.instance.ForceSendZDO(origin.m_uid);
			MineRun mineRun = new MineRun
			{
				Type = type,
				Zone = zone,
				Origin = origin.m_uid,
				Stage = Stage.Generating,
				StartedAt = Time.time,
				HasHome = true,
				Home = origin.GetPosition(),
				HomeRot = origin.GetRotation()
			};
			Runs[zone] = mineRun;
			Registry.Add(zone, type.Id);
			Plugin.Log.LogInfo((object)$"{mineRun.Name}: портал {origin.m_uid} у {origin.GetPosition()}, локация {type.Location.Value} ({val}).");
		}

		public static void StartSelfTest(MineType type)
		{
			//IL_0037: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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 (!type.Enabled.Value || !FindFreeSlot(type, out var zone))
			{
				Plugin.Log.LogWarning((object)("Самопроверка: " + type.Title + " выключен или нет свободных мест."));
				return;
			}
			Vector3 zonePos = ZoneSystem.GetZonePos(zone);
			PurgeInteriorLeftovers(type, zone);
			PrepareVisited(type, zone);
			Vector3 val = default(Vector3);
			if (!ZoneSystem.instance.SpawnLocationMidGame(type.Location.Value, zonePos, ref val))
			{
				Plugin.Log.LogError((object)$"Самопроверка: не удалось зарегистрировать локацию {type.Location.Value} в {zonePos}.");
				return;
			}
			Runs[zone] = new MineRun
			{
				Type = type,
				Zone = zone,
				Stage = Stage.Generating,
				StartedAt = Time.time,
				SelfTest = true
			};
			Registry.Add(zone, type.Id);
			Plugin.Log.LogInfo((object)$"Самопроверка: {type.Title} в зоне {zone} ({val}).");
		}

		private static void Restore(ZDO origin, string typeId, Vector2s zone)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			MineType mineType = Plugin.Types.FirstOrDefault((MineType t) => t.Id == typeId);
			if (mineType == null)
			{
				RetirePortal(origin, "неизвестный вид испытания " + typeId);
				return;
			}
			ZDOID connectionZDOID = origin.GetConnectionZDOID((ConnectionType)1);
			Vector3 center = default(Vector3);
			MineRun mineRun = new MineRun
			{
				Type = mineType,
				Zone = zone,
				Origin = origin.m_uid,
				Stage = Stage.Ready,
				Inner = connectionZDOID,
				StartedAt = Time.time,
				HasHome = true,
				Home = origin.GetPosition(),
				HomeRot = origin.GetRotation(),
				HasCenter = origin.GetVec3(CenterKey, ref center),
				Center = center,
				Populated = origin.GetInt(PopulatedKey, 0),
				Cleared = (origin.GetInt(ClearedKey, 0) != 0),
				Visited = (origin.GetInt(VisitedKey, 0) != 0),
				ReadyAt = origin.GetLong(ReadyAtKey, Now()),
				LastPresence = origin.GetLong(LastPresenceKey, Now())
			};
			ReadIds(origin.GetString(MembersKey, ""), mineRun.Members);
			ReadIds(origin.GetString(RewardedKey, ""), mineRun.Rewarded);
			mineRun.Given.UnionWith(origin.GetString(GivenKey, "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
			ReadIds(origin.GetString(VisitorsKey, ""), mineRun.Visitors);
			ReadZdoIds(origin.GetString(SpawnedKey, ""), mineRun.Spawned);
			Runs[zone] = mineRun;
			Plugin.Log.LogInfo((object)(string.Format("{0}: восстановлено после перезапуска, мобов создано {1}, посещено {2}, ", mineRun.Name, mineRun.Populated, mineRun.Visited ? "да" : "нет") + string.Format("зачищено {0}, участников {1}, награждено {2}.", mineRun.Cleared ? "да" : "нет", mineRun.Members.Count, mineRun.Rewarded.Count)));
			if (((ZDOID)(ref connectionZDOID)).IsNone() || !mineRun.HasCenter)
			{
				Collapse(mineRun, "сервер остановился во время постройки");
			}
		}

		public static bool BlockUsable(MineType type, Vector2s slot)
		{
			//IL_0000: 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)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (Registry.Contains(slot))
			{
				return true;
			}
			if (ZoneSystem.instance.ZoneHasLocation(slot))
			{
				return false;
			}
			if (Pool.BlockZones(slot).Any(IsZoneGenerated))
			{
				if (type.AllowVisited.Value)
				{
					return BlockClean(slot);
				}
				return false;
			}
			return true;
		}

		private static bool BlockClean(Vector2s slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Pool.BlockZones(slot).All((Vector2s zone) => !ZoneObjects(zone).Any((ZDO z) => IsPlayerPiece(z) || IsTombstone(z.GetPrefab())));
		}

		private static void PrepareVisited(MineType type, Vector2s slot)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			Vector2s zone = default(Vector2s);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					((Vector2s)(ref zone))..ctor((short)(slot.x + i), (short)(slot.y + j));
					if (!IsZoneGenerated(zone))
					{
						continue;
					}
					foreach (ZDO item in from z in ZoneObjects(zone)
						where !IsPlayer(z.GetPrefab())
						select z)
					{
						Destroy(item);
						num++;
					}
					Unregister(zone, type.Location.Value);
					num2++;
				}
			}
			if (num2 > 0)
			{
				Plugin.Log.LogInfo((object)$"{type.Title}: место {slot} посещалось — перед испытанием стёрто зон {num2}, объектов {num}; они будут построены заново.");
			}
		}

		private static bool FindFreeSlot(MineType type, out Vector2s zone)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			foreach (Vector2s slot in type.Slots)
			{
				if (!Runs.ContainsKey(slot) && !ZoneSystem.instance.ZoneHasLocation(slot) && (!Pool.BlockZones(slot).Any(IsZoneGenerated) || ((type.SlotsFrom ?? type).AllowVisited.Value && !AnyPlayerInBlock(slot) && BlockClean(slot))))
				{
					zone = slot;
					return true;
				}
			}
			zone = default(Vector2s);
			return false;
		}

		public static void Tick()
		{
			foreach (MineRun item in new List<MineRun>(Runs.Values))
			{
				try
				{
					switch (item.Stage)
					{
					case Stage.Generating:
						Generate(item);
						break;
					case Stage.Ready:
						if (!item.PortalChecked)
						{
							CheckInnerPortal(item);
						}
						KeepSturdy(item);
						TrackPlayers(item);
						UpdateMobs(item);
						Finish(item);
						CheckTimeouts(item);
						break;
					case Stage.Closing:
						TrackPlayers(item);
						TryReset(item);
						break;
					case Stage.Resetting:
						CompleteReset(item);
						break;
					}
				}
				catch (Exception arg)
				{
					item.Stage = Stage.Failed;
					Plugin.Log.LogError((object)$"{item.Name}: ошибка, попытка остановлена (место остаётся занятым): {arg}");
				}
			}
		}

		private static bool IsZoneGenerated(Vector2s zone)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return (bool)_isZoneGenerated.Invoke(ZoneSystem.instance, new object[1] { zone });
		}

		private static void Generate(MineRun run)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: 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)
			if (!IsZoneGenerated(run.Zone))
			{
				_spawnZone.Invoke(ZoneSystem.instance, new object[3]
				{
					run.Zone,
					(object)(SpawnMode)2,
					null
				});
				if (!IsZoneGenerated(run.Zone))
				{
					if (Time.time - run.StartedAt > Plugin.GenerateTimeout.Value)
					{
						Plugin.Log.LogError((object)$"{run.Name}: зона не сгенерировалась за {Plugin.GenerateTimeout.Value} с.");
						Collapse(run, "зона не сгенерировалась");
					}
					return;
				}
				Plugin.Log.LogInfo((object)$"{run.Name}: зона сгенерирована за {Time.time - run.StartedAt:0.0} с.");
			}
			Vector3 pos;
			Quaternion rot;
			bool flag = (run.Type.Interior ? FindDungeonEntry(run, out pos, out rot) : FindAreaEntry(run, out pos, out rot));
			if (run.SelfTest)
			{
				Plugin.Log.LogInfo((object)("Самопроверка: " + run.Name + " " + (flag ? $"— вход найден, портал встал бы в {pos}" : "— вход не найден") + "."));
				if (flag && run.Type.Interior)
				{
					LogRooms(run);
				}
				if (flag)
				{
					Populate(run, pos);
					UpdateMobs(run);
				}
				Collapse(run, "самопроверка");
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(run.Origin);
			if (zDO == null)
			{
				Collapse(run, "исходный портал исчез до готовности");
				return;
			}
			if (!flag)
			{
				Collapse(run, "не найден вход");
				return;
			}
			ZDO val = CreateInnerPortal(run, pos, rot, zDO.GetString(ZDOVars.s_tag, ""));
			if (val == null)
			{
				Collapse(run, "не создан ответный портал");
				return;
			}
			Populate(run, pos);
			zDO.Set(PopulatedKey, run.Populated, false);
			zDO.Set(SpawnedKey, WriteZdoIds(run.Spawned));
			zDO.Set(CenterKey, run.Center);
			Connect(zDO, val.m_uid);
			Connect(val, zDO.m_uid);
			run.Inner = val.m_uid;
			run.ReadyAt = (run.LastPresence = Now());
			zDO.Set(ReadyAtKey, run.ReadyAt);
			zDO.Set(LastPresenceKey, run.LastPresence);
			run.Stage = Stage.Ready;
			run.PortalChecked = true;
			Plugin.Log.LogInfo((object)$"{run.Name}: готово, ответный портал {val.m_uid} в {pos}.");
		}

		private static void CheckInnerPortal(MineRun run)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			run.PortalChecked = true;
			if (!run.Type.Interior || ((ZDOID)(ref run.Inner)).IsNone())
			{
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(run.Origin);
			ZDO zDO2 = ZDOMan.instance.GetZDO(run.Inner);
			if (zDO == null || zDO2 == null || !FindDungeonEntry(run, out var pos, out var rot))
			{
				return;
			}
			float num = Vector3.Distance(zDO2.GetPosition(), pos);
			if (!(num <= 2f))
			{
				ZDO val = CreateInnerPortal(run, pos, rot, zDO.GetString(ZDOVars.s_tag, ""));
				if (val != null)
				{
					Connect(zDO, val.m_uid);
					Connect(val, zDO.m_uid);
					Destroy(zDO2);
					run.Inner = val.m_uid;
					run.HasRelocation = true;
					run.RelocatedPos = pos;
					run.RelocatedRot = rot;
					Plugin.Log.LogWarning((object)$"{run.Name}: ответный портал стоял в {zDO2.GetPosition()}, в {num:0} м от нужного места — перенесён в {pos} ({val.m_uid}).");
				}
			}
		}

		private static void Connect(ZDO portal, ZDOID target)
		{
			//IL_000d: 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)
			portal.SetOwner(ZDOMan.GetSessionID());
			portal.SetConnection((ConnectionType)1, target);
			ZDOMan.instance.ForceSendZDO(portal.m_uid);
		}

		internal static void Destroy(ZDO zdo)
		{
			zdo.SetOwner(ZDOMan.GetSessionID());
			ZDOMan.instance.DestroyZDO(zdo);
		}

		private static List<ZDO> ZoneObjects(Vector2s zone)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO>[] array = (List<ZDO>[])_objectsBySector.GetValue(ZDOMan.instance);
			uint sector = ZoneSystem.SectorToIndex(zone).Sector;
			List<ZDO> list = ((sector < array.Length) ? array[sector] : null);
			if (list == null)
			{
				return new List<ZDO>();
			}
			return new List<ZDO>(list);
		}

		private static List<ZDO> AreaObjects(MineRun run)
		{
			//IL_00d1: 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)
			List<ZDO> list = new List<ZDO>();
			if (run.Type.Interior)
			{
				for (int i = -1; i <= 1; i++)
				{
					for (int j = -1; j <= 1; j++)
					{
						list.AddRange(from z in ZoneObjects(new Vector2s(run.Zone.x + i, run.Zone.y + j))
							where InArea(run, z.GetPosition())
							select z);
					}
				}
				return list;
			}
			Vector2s zone = default(Vector2s);
			for (int num = -1; num <= 1; num++)
			{
				for (int num2 = -1; num2 <= 1; num2++)
				{
					((Vector2s)(ref zone))..ctor(run.Zone.x + num, run.Zone.y + num2);
					list.AddRange(from z in ZoneObjects(zone)
						where InArea(run, z.GetPosition())
						select z);
				}
			}
			return list;
		}

		private static bool InArea(MineRun run, Vector3 p)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (run.Type.Interior)
			{
				if (p.y < 3000f)
				{
					return false;
				}
				if (!run.RoomsTried)
				{
					LoadRooms(run);
				}
				if (!run.HasRoomBounds)
				{
					return ZoneSystem.GetZone(p) == run.Zone;
				}
				if (p.x >= run.RoomMin.x && p.x <= run.RoomMax.x && p.z >= run.RoomMin.y)
				{
					return p.z <= run.RoomMax.y;
				}
				return false;
			}
			if (!run.HasCenter || p.y >= 3000f)
			{
				return false;
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(p.x - run.Center.x, p.z - run.Center.z);
			return ((Vector2)(ref val)).magnitude <= run.Type.AreaRadius.Value;
		}

		private static string RoomName(int hash)
		{
			RoomData val = (((Object)(object)DungeonDB.instance != (Object)null) ? DungeonDB.instance.GetRoom(hash) : null);
			if (val == null)
			{
				return "";
			}
			return val.m_prefab.Name;
		}

		private static void PurgeInteriorLeftovers(MineType type, Vector2s slot)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			List<string> list = new List<string>();
			byte[] array = default(byte[]);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					foreach (ZDO item in ZoneObjects(new Vector2s(slot.x + i, slot.y + j)))
					{
						if (!(item.GetPosition().y < 3000f) && !IsPlayer(item.GetPrefab()) && !IsTombstone(item.GetPrefab()))
						{
							if (item.GetByteArray(ZDOVars.s_roomData, ref array) || KindOf(item.GetPrefab()) == PrefabKind.Creature)
							{
								list.Add(PrefabName(item.GetPrefab()));
							}
							Destroy(item);
							num++;
						}
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogWarning((object)($"{type.Title} {slot}: перед постройкой удалены остатки прежних испытаний внутри подземелий — {num} объектов" + ((list.Count > 0) ? (" (генераторы и существа: " + Summary(list) + ")") : "") + "."));
			}
		}

		private static bool IsOwnGenerator(MineRun run, ZDO zdo)
		{
			string text = PrefabName(zdo.GetPrefab());
			string text2 = (text.StartsWith("DG_") ? text.Substring(3) : text);
			if (text2.Length > 0)
			{
				return run.Type.Location.Value.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static ZDO LoadRooms(MineRun run)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			run.RoomsTried = true;
			List<ZDO> list = new List<ZDO>();
			byte[] array2 = default(byte[]);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					list.AddRange(from z in ZoneObjects(new Vector2s(run.Zone.x + i, run.Zone.y + j))
						where z.GetPosition().y >= 3000f && z.GetByteArray(ZDOVars.s_roomData, ref array2)
						select z);
				}
			}
			ZDO own = ((IEnumerable<ZDO>)list).FirstOrDefault((Func<ZDO, bool>)((ZDO z) => IsOwnGenerator(run, z)));
			if (own != null)
			{
				foreach (ZDO item in list.Where((ZDO z) => z != own && !IsOwnGenerator(run, z)).ToList())
				{
					Plugin.Log.LogWarning((object)$"{run.Name}: чужой генератор подземелья {PrefabName(item.GetPrefab())} {item.m_uid} в {Round(item.GetPosition())} удалён.");
					Destroy(item);
					list.Remove(item);
				}
				list.Remove(own);
				list.Insert(0, own);
			}
			byte[] array = default(byte[]);
			Vector3 value = default(Vector3);
			Vector2 val = default(Vector2);
			foreach (ZDO item2 in list)
			{
				if (!item2.GetByteArray(ZDOVars.s_roomData, ref array))
				{
					continue;
				}
				run.Rooms.Clear();
				using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(array)))
				{
					int num = binaryReader.ReadInt32();
					int num2 = ((num > 0) ? ((array.Length - 4) / num) : 0);
					if (num2 < 16 || 4 + num2 * num != array.Length)
					{
						Plugin.Log.LogError((object)$"{run.Name}: неизвестный формат roomData ({array.Length} байт, комнат {num}).");
						continue;
					}
					for (int num3 = 0; num3 < num; num3++)
					{
						int key = binaryReader.ReadInt32();
						((Vector3)(ref value))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
						binaryReader.ReadBytes(num2 - 16);
						run.Rooms.Add(new KeyValuePair<int, Vector3>(key, value));
					}
				}
				if (run.Rooms.Count == 0)
				{
					continue;
				}
				Vector3 position = item2.GetPosition();
				((Vector2)(ref val))..ctor(position.x, position.z);
				Vector2 val2 = val;
				foreach (KeyValuePair<int, Vector3> room in run.Rooms)
				{
					val = Vector2.Min(val, new Vector2(room.Value.x, room.Value.z));
					val2 = Vector2.Max(val2, new Vector2(room.Value.x, room.Value.z));
				}
				run.RoomMin = val - Vector2.one * 24f;
				run.RoomMax = val2 + Vector2.one * 24f;
				run.HasRoomBounds = true;
				return item2;
			}
			return null;
		}

		private static void LogRooms(MineRun run)
		{
			//IL_0001: 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_00b1: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = default(byte[]);
			Vector3 val = default(Vector3);
			foreach (ZDO item in ZoneObjects(run.Zone))
			{
				if (item.GetPosition().y < 3000f || !item.GetByteArray(ZDOVars.s_roomData, ref array))
				{
					continue;
				}
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(array));
				int num = binaryReader.ReadInt32();
				int num2 = (array.Length - 4) / num;
				for (int i = 0; i < num; i++)
				{
					int num3 = binaryReader.ReadInt32();
					((Vector3)(ref val))..ctor(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
					Quaternion val2 = (Quaternion)((num2 >= 32) ? new Quaternion(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()) : Quaternion.identity);
					if (num2 > 32)
					{
						binaryReader.ReadBytes(num2 - 32);
					}
					if (num2 > 16 && num2 < 32)
					{
						binaryReader.ReadBytes(num2 - 16);
					}
					RoomData room = DungeonDB.instance.GetRoom(num3);
					string text = "?";
					if (room != null)
					{
						room.m_prefab.Load();
						try
						{
							Room roomInPrefab = room.RoomInPrefab;
							text = (((Object)(object)roomInPrefab == (Object)null) ? room.m_prefab.Name : string.Format("{0} size {1} {2}{3}{4}", room.m_prefab.Name, roomInPrefab.m_size, roomInPrefab.m_entrance ? "entrance " : "", roomInPrefab.m_endCap ? "endcap " : "", roomInPrefab.m_divider ? "divider" : ""));
						}
						finally
						{
							room.m_prefab.Release();
						}
					}
					Plugin.Log.LogInfo((object)$"{run.Name}: комната {i}: {text} в {Round(val)} (от входа {val - item.GetPosition()}), поворот {((Quaternion)(ref val2)).eulerAngles.y:0}°.");
				}
				break;
			}
		}

		private static bool FindDungeonEntry(MineRun run, out Vector3 pos, out Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: 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_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			rot = Quaternion.identity;
			ZDO val = LoadRooms(run);
			if (val == null)
			{
				Plugin.Log.LogError((object)$"{run.Name}: не найден генератор подземелья (roomData выше {3000f} м).");
				return false;
			}
			Vector3 position = val.GetPosition();
			Vector3 value = run.Rooms[0].Value;
			run.Door = position;
			run.Center = position;
			run.HasCenter = true;
			Vector3 val2 = value - position;
			val2.y = 0f;
			val2 = ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val2)).normalized : (val.GetRotation() * Vector3.forward));
			pos = position + val2 * run.Type.EntryOffset.Value + Vector3.up * Plugin.EntryHeight.Value;
			rot = Quaternion.LookRotation(val2);
			string text = RoomName(run.Rooms[0].Key);
			if (text.IndexOf("bossroom_ENTRANCE", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				pos = position + val2 * run.Type.EntryOffset.Value + Vector3.up * (-1.6f + Plugin.EntryHeight.Value);
				Plugin.Log.LogInfo((object)$"{run.Name}: зал {text} — портал на полу зала в {run.Type.EntryOffset.Value:0} м от входа.");
			}
			Vector3 zonePos = ZoneSystem.GetZonePos(run.Zone);
			float num = Mathf.Max(new float[4]
			{
				Mathf.Abs(run.RoomMin.x - zonePos.x),
				Mathf.Abs(run.RoomMax.x - zonePos.x),
				Mathf.Abs(run.RoomMin.y - zonePos.z),
				Mathf.Abs(run.RoomMax.y - zonePos.z)
			});
			Plugin.Log.LogInfo((object)($"{run.Name}: генератор {val.m_uid} у входа {position}, комнат {run.Rooms.Count}, первая комната {value}; " + string.Format("границы подземелья {0}–{1} (до {2:0} м от центра зоны{3}).", run.RoomMin, run.RoomMax, num, (num > 32f) ? ", выходит за зону" : "")));
			return true;
		}

		private static bool FindAreaEntry(MineRun run, out Vector3 pos, out Quaternion rot)
		{
			//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: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			rot = Quaternion.identity;
			int proxy = StringExtensionMethods.GetStableHashCode(((Object)ZoneSystem.instance.m_locationProxyPrefab).name);
			ZDO val = ((IEnumerable<ZDO>)ZoneObjects(run.Zone)).FirstOrDefault((Func<ZDO, bool>)((ZDO z) => z.GetPrefab() == proxy));
			if (val == null)
			{
				Plugin.Log.LogError((object)(run.Name + ": не найден LocationProxy локации."));
				return false;
			}
			run.Center = val.GetPosition();
			run.HasCenter = true;
			Vector3 val2 = new Vector3(run.Center.x, 0f, run.Center.z);
			Vector3 val3 = -((Vector3)(ref val2)).normalized;
			pos = run.Center + val3 * run.Type.EntryOffset.Value;
			pos.y = run.Center.y + Plugin.EntryHeight.Value;
			rot = Quaternion.LookRotation(-val3);
			float height = WorldGenerator.instance.GetHeight(pos.x, pos.z);
			Plugin.Log.LogInfo((object)$"{run.Name}: центр локации {run.Center}, портал в {pos} (высота рельефа по генератору {height:0.0}).");
			return true;
		}

		private static ZDO CreateInnerPortal(MineRun run, Vector3 pos, Quaternion rot, string tag)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab(Plugin.InnerPortalPrefab.Value);
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<TeleportWorld>() == (Object)null)
			{
				Plugin.Log.LogError((object)("Префаб " + Plugin.InnerPortalPrefab.Value + " не найден или не портал."));
				return null;
			}
			ZDO obj = CreateObject(prefab, pos, rot);
			obj.Set(ZDOVars.s_tag, tag);
			obj.Set(InnerKey, 1, false);
			obj.Set(ZDOVars.s_health, 10000000f);
			return obj;
		}

		private static void KeepSturdy(MineRun run)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = (((ZDOID)(ref run.Inner)).IsNone() ? null : ZDOMan.instance.GetZDO(run.Inner));
			float num = ((val != null) ? val.GetFloat(ZDOVars.s_health, -1f) : 10000000f);
			if (val != null && num != 0f && num < 5000000f)
			{
				val.Set(ZDOVars.s_health, 10000000f);
			}
		}

		internal static ZDO CreateObject(GameObject prefab, Vector3 pos, Quaternion rot)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = prefab.GetComponent<ZNetView>();
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			object obj = EwpSkip?.GetValue(null);
			ZDO val;
			try
			{
				EwpSkip?.SetValue(null, true);
				val = ZDOMan.instance.CreateNewZDO(pos, stableHashCode);
			}
			finally
			{
				if (obj != null)
				{
					EwpSkip.SetValue(null, obj);
				}
			}
			val.Persistent = component.m_persistent;
			val.Type = component.m_type;
			val.Distant = component.m_distant;
			val.SetPrefab(stableHashCode);
			val.SetRotation(rot);
			return val;
		}

		private static void TrackPlayers(MineRun run)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0051: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (((ZDOID)(ref peer.m_characterID)).IsNone())
				{
					continue;
				}
				ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
				if (zDO == null)
				{
					continue;
				}
				Vector3 position = zDO.GetPosition();
				bool flag = Pool.InBlock(run.Zone, position);
				bool flag2 = InArea(run, position);
				long num = zDO.GetLong(ZDOVars.s_playerID, 0L);
				if (flag2 && num != 0L && run.Visitors.Add(num))
				{
					ZDO zDO2 = ZDOMan.instance.GetZDO(run.Origin);
					if (zDO2 != null)
					{
						zDO2.Set(VisitorsKey, WriteIds(run.Visitors));
					}
				}
				if (run.Cleared && !flag2)
				{
					RewardOnExit(run, num);
				}
				if (flag2 && run.HasRelocation && run.Relocated.Add(peer.m_uid))
				{
					Vector3 val = run.RelocatedPos + run.RelocatedRot * Vector3.forward * 1.5f + Vector3.up;
					ZRoutedRpc.instance.InvokeRoutedRPC(zDO.GetOwner(), peer.m_characterID, "RPC_TeleportTo", new object[3] { val, run.RelocatedRot, true });
					Plugin.Log.LogInfo((object)(run.Name + ": " + peer.m_playerName + " перенесён к новому месту ответного портала."));
				}
				if (flag2)
				{
					run.Returning.Remove(peer.m_uid);
					if (run.Inside.Add(peer.m_uid))
					{
						MarkPresence(run, entered: true);
						Plugin.Log.LogInfo((object)(run.Name + ": вошёл " + peer.m_playerName + "."));
						if (!run.Cleared && run.LastMobs > 0 && run.Stage == Stage.Ready)
						{
							string text = ((run.Type.BossLevel.Value > 3 && run.Type.BossPrefab.Value != "") ? $" Босс уровня {run.Type.BossLevel.Value}." : "");
							string text2 = ((run.Type.RewardCount.Value > 1) ? $"получите {run.Type.RewardCount.Value} награды" : "получите награду");
							Message(peer.m_uid, $"{run.Type.Title}. Врагов: {run.LastMobs}.{text} Перебейте всех — {text2}.");
						}
					}
					continue;
				}
				if (run.Inside.Remove(peer.m_uid))
				{
					if (!flag)
					{
						Plugin.Log.LogInfo((object)(run.Name + ": " + peer.m_playerName + " ушёл через портал или погиб."));
						continue;
					}
					run.Returning[peer.m_uid] = Time.time + 20f;
					Plugin.Log.LogInfo((object)(run.Name + ": " + peer.m_playerName + " вышел за пределы испытания, возвращаю к порталу."));
				}
				if (run.Returning.TryGetValue(peer.m_uid, out var value))
				{
					if (!flag)
					{
						run.Returning.Remove(peer.m_uid);
						Plugin.Log.LogInfo((object)$"{run.Name}: {peer.m_playerName} возвращён, сейчас в {position}.");
					}
					else if (Time.time > value)
					{
						run.Returning.Remove(peer.m_uid);
						Plugin.Log.LogWarning((object)$"{run.Name}: не удалось вернуть {peer.m_playerName} за {20f} с, он остался в {position}.");
					}
					else
					{
						ReturnHome(run, peer, zDO);
					}
				}
			}
		}

		private static void ReturnHome(MineRun run, ZNetPeer peer, ZDO player)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!run.HasHome)
			{
				Plugin.Log.LogWarning((object)(run.Name + ": " + peer.m_playerName + " вышел, но точка возврата неизвестна."));
				run.Returning.Remove(peer.m_uid);
				return;
			}
			Quaternion homeRot = run.HomeRot;
			Vector3 val = run.Home + homeRot * Vector3.forward * 1.5f + Vector3.up;
			ZRoutedRpc.instance.InvokeRoutedRPC(player.GetOwner(), peer.m_characterID, "RPC_TeleportTo", new object[3] { val, homeRot, true });
		}

		internal static void Message(long peerUid, string text)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(peerUid, "ShowMessage", new object[2] { 2, text });
		}

		private static void ReadIds(string text, HashSet<long> ids)
		{
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				if (long.TryParse(array[i], out var result) && result != 0L)
				{
					ids.Add(result);
				}
			}
		}

		private static string WriteIds(HashSet<long> ids)
		{
			return string.Join(",", ids);
		}

		private static void ReadZdoIds(string text, HashSet<ZDOID> ids)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && long.TryParse(array2[0], out var result) && uint.TryParse(array2[1], out var result2))
				{
					ids.Add(new ZDOID(result, result2));
				}
			}
		}

		private static string WriteZdoIds(HashSet<ZDOID> ids)
		{
			return string.Join(",", ids.Select((ZDOID z) => $"{((ZDOID)(ref z)).UserID}:{((ZDOID)(ref z)).ID}"));
		}

		private static void Populate(MineRun run, Vector3 entry)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<ZDO, CreatureSpawner>> list = new List<KeyValuePair<ZDO, CreatureSpawner>>();
			foreach (ZDO item in AreaObjects(run))
			{
				if (KindOf(item.GetPrefab()) == PrefabKind.Spawner)
				{
					CreatureSpawner component = ZNetScene.instance.GetPrefab(item.GetPrefab()).GetComponent<CreatureSpawner>();
					list.Add(new KeyValuePair<ZDO, CreatureSpawner>(item, component));
				}
			}
			int num = 0;
			int num2 = 0;
			int[] levels = new int[8];
			string text = run.Type.BossPrefab.Value.Trim();
			bool flag = text != "" && PromoteExistingBoss(run, text);
			if (flag)
			{
				num++;
			}
			foreach (KeyValuePair<ZDO, CreatureSpawner> item2 in ChooseSpawners(list))
			{
				CreatureSpawner value = item2.Value;
				if ((Object)(object)value.m_creaturePrefab == (Object)null || !GlobalKeysAllow(value))
				{
					num2++;
					continue;
				}
				Vector3 position = item2.Key.GetPosition();
				bool flag2 = text != "" && ((Object)value.m_creaturePrefab).name == text;
				if (flag2 && flag)
				{
					num2++;
					continue;
				}
				int num3 = (flag2 ? Mathf.Max(run.Type.BossLevel.Value, 1) : RollLevel(value, run.Type.MinLevel.Value));
				if (flag2)
				{
					flag = true;
					Plugin.Log.LogInfo((object)$"{run.Name}: босс {text} уровня {num3} на месте своего спавнера {Round(position)}.");
				}
				ZDO val = CreateObject(value.m_creaturePrefab, position, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				run.Spawned.Add(val.m_uid);
				val.Set(ZDOVars.s_level, num3, false);
				if (value.m_setPatrolSpawnPoint)
				{
					val.Set(ZDOVars.s_patrolPoint, position);
					val.Set(ZDOVars.s_patrol, true);
				}
				num++;
				levels[Mathf.Min(num3, levels.Length - 1)]++;
			}
			foreach (KeyValuePair<ZDO, CreatureSpawner> item3 in list)
			{
				Destroy(item3.Key);
			}
			if (!flag && SpawnBoss(run, entry))
			{
				num++;
			}
			run.Populated = num;
			string text2 = string.Join(", ", from l in Enumerable.Range(1, levels.Length - 1)
				where levels[l] > 0
				select $"{l - 1}★ — {levels[l]}");
			Plugin.Log.LogInfo((object)$"{run.Name}: спавнеров {list.Count}, создано мобов {num} с боссом ({text2}), пропущено {num2}; спавнеры удалены.");
		}

		private static bool PromoteExistingBoss(MineRun run, string bossName)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			int hash = StringExtensionMethods.GetStableHashCode(bossName);
			bool flag = false;
			Vector3 hall = ((run.Rooms.Count > 0) ? run.Rooms[0].Value : run.Door);
			foreach (ZDO item in (from z in AreaObjects(run)
				where z.GetPrefab() == hash
				select z).OrderBy(delegate(ZDO z)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				Vector2 val2 = new Vector2(z.GetPosition().x - hall.x, z.GetPosition().z - hall.z);
				return ((Vector2)(ref val2)).magnitude;
			}))
			{
				if (flag)
				{
					Destroy(item);
					Plugin.Log.LogWarning((object)(run.Name + ": лишний " + bossName + " " + Round(item.GetPosition()) + " удалён."));
				}
				else
				{
					Vector3 position = item.GetPosition();
					ZDO val = Upgrade(item, Mathf.Max(run.Type.BossLevel.Value, 1));
					run.Spawned.Add(val.m_uid);
					flag = true;
					Plugin.Log.LogInfo((object)$"{run.Name}: босс {bossName} подземелья {Round(position)} поднят до уровня {run.Type.BossLevel.Value}.");
				}
			}
			return flag;
		}

		private static bool SpawnBoss(MineRun run, Vector3 entry)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			string text = run.Type.BossPrefab.Value.Trim();
			if (text == "")
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(text);
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<Character>() == (Object)null)
			{
				Plugin.Log.LogError((object)(run.Name + ": босс " + text + " не найден или не существо — без босса."));
				return false;
			}
			Vector3 val;
			string text2;
			Vector3 best;
			if (run.Type.Interior)
			{
				if (!BossRoom(run, out best))
				{
					Plugin.Log.LogError((object)(run.Name + ": не найдено подходящей комнаты для босса — без босса."));
					return false;
				}
				val = run.Door - best;
				text2 = $"в комнате {best} в {Vector3.Distance(best, run.Door):0} м от входа";
				best += Vector3.up * 0.5f;
			}
			else
			{
				Vector3 val2 = run.Center - entry;
				val2.y = 0f;
				val2 = ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val2)).normalized : Vector3.forward);
				best = run.Center + val2 * Mathf.Min(10f, run.Type.AreaRadius.Value * 0.5f) + Vector3.up;
				val = -val2;
				text2 = $"в {best}, напротив портала";
			}
			val.y = 0f;
			ZDO val3 = CreateObject(prefab, best, (((Vector3)(ref val)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val) : Quaternion.identity);
			val3.Set(ZDOVars.s_level, Mathf.Max(run.Type.BossLevel.Value, 1), false);
			run.Spawned.Add(val3.m_uid);
			Plugin.Log.LogInfo((object)$"{run.Name}: босс {text} уровня {run.Type.BossLevel.Value} {text2}.");
			return true;
		}

		private static bool BossRoom(MineRun run, out Vector3 best)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			best = Vector3.zero;
			float num = 0f;
			float num2 = -1f;
			Dictionary<int, float> dictionary = new Dictionary<int, float>();
			foreach (KeyValuePair<int, Vector3> room in run.Rooms)
			{
				if (!dictionary.TryGetValue(room.Key, out var value))
				{
					value = RoomArea(room.Key);
					dictionary[room.Key] = value;
				}
				float num3 = Vector3.Distance(room.Value, run.Door);
				if (value > num || (value > 0f && Mathf.Approximately(value, num) && num3 > num2))
				{
					best = room.Value;
					num = value;
					num2 = num3;
				}
			}
			return num > 0f;
		}

		private static float RoomArea(int hash)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			RoomData room = DungeonDB.instance.GetRoom(hash);
			if (room == null)
			{
				return 0f;
			}
			room.m_prefab.Load();
			try
			{
				Room roomInPrefab = room.RoomInPrefab;
				if ((Object)(object)roomInPrefab == (Object)null || roomInPrefab.m_entrance || roomInPrefab.m_endCap || roomInPrefab.m_divider)
				{
					return 0f;
				}
				return ((Vector3Int)(ref roomInPrefab.m_size)).x * ((Vector3Int)(ref roomInPrefab.m_size)).z;
			}
			finally
			{
				room.m_prefab.Release();
			}
		}

		private static IEnumerable<KeyValuePair<ZDO, CreatureSpawner>> ChooseSpawners(List<KeyValuePair<ZDO, CreatureSpawner>> spawners)
		{
			HashSet<int> grouped = new HashSet<int>();
			for (int i = 0; i < spawners.Count; i++)
			{
				CreatureSpawner value = spawners[i].Value;
				if (value.m_spawnGroupID == 0)
				{
					yield return spawners[i];
				}
				else
				{
					if (grouped.Contains(i))
					{
						continue;
					}
					List<int> list = new List<int> { i };
					grouped.Add(i);
					for (int j = 0; j < list.Count; j++)
					{
						KeyValuePair<ZDO, CreatureSpawner> keyValuePair = spawners[list[j]];
						for (int k = 0; k < spawners.Count; k++)
						{
							KeyValuePair<ZDO, CreatureSpawner> keyValuePair2 = spawners[k];
							if (!grouped.Contains(k) && keyValuePair2.Value.m_spawnGroupID == value.m_spawnGroupID)
							{
								float num = Mathf.Max(keyValuePair.Value.m_spawnGroupRadius, keyValuePair2.Value.m_spawnGroupRadius);
								if (Vector3.Distance(keyValuePair.Key.GetPosition(), keyValuePair2.Key.GetPosition()) <= num)
								{
									grouped.Add(k);
									list.Add(k);
								}
							}
						}
					}
					int max = Mathf.Max(1, value.m_maxGroupSpawned);
					List<int> pool = new List<int>(list);
					for (int n = 0; n < max; n++)
					{
						if (pool.Count <= 0)
						{
							break;
						}
						float num2 = pool.Sum((int index) => Mathf.Max(0.01f, spawners[index].Value.m_spawnerWeight));
						float num3 = Random.Range(0f, num2);
						int num4 = pool[pool.Count - 1];
						foreach (int item in pool)
						{
							num3 -= Mathf.Max(0.01f, spawners[item].Value.m_spawnerWeight);
							if (num3 <= 0f)
							{
								num4 = item;
								break;
							}
						}
						pool.Remove(num4);
						yield return spawners[num4];
					}
				}
			}
		}

		private static bool GlobalKeysAllow(CreatureSpawner spawner)
		{
			if (spawner.m_blockingGlobalKey != "" && ZoneSystem.instance.GetGlobalKey(spawner.m_blockingGlobalKey))
			{
				return false;
			}
			if (!(spawner.m_requiredGlobalKey == ""))
			{
				return ZoneSystem.instance.GetGlobalKey(spawner.m_requiredGlobalKey);
			}
			return true;
		}

		private static int RollLevel(CreatureSpawner spawner, int minLevel)
		{
			int i = spawner.m_minLevel;
			if (spawner.m_maxLevel > 1)
			{
				for (; i < spawner.m_maxLevel; i++)
				{
					if (!(Random.Range(0f, 100f) <= spawner.m_levelupChance))
					{
						break;
					}
				}
			}
			return Mathf.Max(i, minLevel);
		}

		private static void UpdateMobs(MineRun run)
		{
			int num = 0;
			int num2 = 0;
			List<string> list = new List<string>();
			List<ZDO> list2 = new List<ZDO>();
			foreach (ZDO item in AreaObjects(run))
			{
				switch (KindOf(item.GetPrefab()))
				{
				case PrefabKind.Creature:
					if (!item.GetBool(ZDOVars.s_tamed, false))
					{
						num++;
						list2.Add(item);
						if (item.GetInt(ZDOVars.s_level, 1) < run.Type.MinLevel.Value && !run.SelfTest)
						{
							list.Add(PrefabName(item.GetPrefab()));
							Upgrade(item, run.Type.MinLevel.Value);
						}
					}
					break;
				case PrefabKind.Spawner:
				case PrefabKind.Nest:
					num2++;
					break;
				}
			}
			if (list.Count > 0)
			{
				Plugin.Log.LogInfo((object)$"{run.Name}: пересозданы со звездой ({list.Count}): {Summary(list)}.");
			}
			if (num != run.LastMobs || num2 != run.LastSpawners)
			{
				bool flag = run.LastMobs > 0 && num < run.LastMobs;
				run.LastMobs = num;
				run.LastSpawners = num2;
				run.MobsChangedAt = Time.time;
				run.StallReported = false;
				Plugin.Log.LogInfo((object)$"{run.Name}: существ {num}, спавнеров и гнёзд {num2}, игроков внутри {run.Inside.Count}.");
				if (flag && num > 0 && !run.Cleared && (num <= 10 || num % 10 == 0) && Time.time - run.LastHintAt >= 5f)
				{
					run.LastHintAt = Time.time;
					foreach (long item2 in run.Inside)
					{
						Message(item2, $"Осталось врагов: {num}.");
					}
				}
			}
			else if (num > 0 && !run.Cleared && !run.StallReported && run.Inside.Count > 0 && run.Stage == Stage.Ready && Time.time - run.MobsChangedAt >= 120f)
			{
				ReportStall(run, list2);
			}
			if (run.Cleared || (run.Populated <= 0 && run.Spawned.Count == 0) || run.SelfTest || run.Stage != Stage.Ready)
			{
				return;
			}
			if (run.Type.Interior)
			{
				bool flag2 = run.Spawned.Count > 0 && run.Spawned.All((ZDOID id) => ZDOMan.instance.GetZDO(id) == null);
				if (num2 == 0 && (num == 0 || flag2))
				{
					OnCleared(run);
				}
				return;
			}
			int num3 = run.Spawned.Count((ZDOID id) => ZDOMan.instance.GetZDO(id) != null);
			if (run.Spawned.Count == 0)
			{
				int boss = StringExtensionMethods.GetStableHashCode(run.Type.BossPrefab.Value.Trim());
				num3 = AreaObjects(run).Count((ZDO z) => z.GetPrefab() == boss);
			}
			if (num3 == 0)
			{
				OnCleared(run);
			}
		}

		private static void ReportStall(MineRun run, List<ZDO> alive)
		{
			//IL_003d: 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_0042: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			run.StallReported = true;
			if (alive.Count == 0)
			{
				return;
			}
			Vector3 origin = (run.HasCenter ? run.Center : Vector3.zero);
			string text = string.Join("; ", from z in alive.Take(20)
				select string.Format("{0} ур.{1} {2} ({3:0} м от {4})", PrefabName(z.GetPrefab()), z.GetInt(ZDOVars.s_level, 1), Round(z.GetPosition()), Vector3.Distance(z.GetPosition(), origin), run.T