Decompiled source of SummitWatch v0.1.4

SummitWatch.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.Unity;
using SummitWatch.Core;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SummitWatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyInformationalVersion("0.1.4")]
[assembly: AssemblyProduct("Summit Watch")]
[assembly: AssemblyTitle("SummitWatch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.4.0")]
[module: UnverifiableCode]
[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 SummitWatch
{
	internal static class Context
	{
		private static Tornado[] _tornadoes = (Tornado[])(object)new Tornado[0];

		private static float _nextTornadoScan;

		private static ScoutCannon[] _cannons = (ScoutCannon[])(object)new ScoutCannon[0];

		private static float _nextCannonScan;

		private static VenusFlyTrap[] _flyTraps = (VenusFlyTrap[])(object)new VenusFlyTrap[0];

		private static FrogTongue[] _frogs = (FrogTongue[])(object)new FrogTongue[0];

		private static float _nextCreatureScan;

		private static Spider[] _spiders = (Spider[])(object)new Spider[0];

		private static RescueHook[] _hooks = (RescueHook[])(object)new RescueHook[0];

		private static float _nextHaulScan;

		private static Collider[] _bouncers = (Collider[])(object)new Collider[0];

		private static float _nextBouncerScan;

		public static string NameOf(Character c)
		{
			return WarningText.SanitizeName(((Object)(object)c != (Object)null) ? c.characterName : null);
		}

		public static bool IsDownOrCarried(Character c)
		{
			if (!((Object)(object)c == (Object)null) && !((Object)(object)c.data == (Object)null) && !c.data.dead && !c.data.fullyPassedOut)
			{
				return c.data.isCarried;
			}
			return true;
		}

		public static bool Holding<T>(Character c) where T : Component
		{
			Item val = (((Object)(object)c != (Object)null && (Object)(object)c.data != (Object)null) ? c.data.currentItem : null);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)((Component)val).GetComponentInChildren<T>() != (Object)null;
			}
			return false;
		}

		private static bool HasBalloons(Character c)
		{
			if (c.refs != null && (Object)(object)c.refs.balloons != (Object)null)
			{
				if (c.refs.balloons.currentBalloonCount <= 0)
				{
					return c.refs.balloons._isParachuteOpen;
				}
				return true;
			}
			return false;
		}

		private static bool WearingJetpack(Character c)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			Player player = c.player;
			BackpackSlot val = (((Object)(object)player != (Object)null) ? player.backpackSlot : null);
			if (val != null && !((ItemSlot)val).IsEmpty())
			{
				if ((int)val.backpackType != 3)
				{
					return (int)val.backpackType == 4;
				}
				return true;
			}
			return false;
		}

		public static bool FlightExempt(Character c)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!HasBalloons(c) && !WearingJetpack(c) && !Context.Holding<JetpackItem>(c) && !Context.Holding<Parasol>(c) && !Has(c, (AfflictionType)17))
			{
				return NearTornado(c.Center, 30f);
			}
			return true;
		}

		public static bool LandingExempt(Character c)
		{
			if (!HasBalloons(c) && !Context.Holding<Parasol>(c) && !Has(c, (AfflictionType)17) && !Invincible(c))
			{
				return RunSetting(() => Ascents.fallDamageMultiplier) == 0f;
			}
			return true;
		}

		public static bool Hanging(Character c)
		{
			if ((Object)(object)c.data != (Object)null)
			{
				if (!((Object)(object)c.data.currentClimbHandle != (Object)null) && !c.data.isVineClimbing)
				{
					return c.data.timeInAntigrav > 0f;
				}
				return true;
			}
			return false;
		}

		public static bool HungerBlocked(Character c)
		{
			if (!Has(c, (AfflictionType)21) && !Invincible(c) && !IsSkeleton(c))
			{
				return RunSetting(() => Ascents.hungerRateMultiplier) == 0f;
			}
			return true;
		}

		public static bool IsSkeleton(Character c)
		{
			if ((Object)(object)c.data != (Object)null)
			{
				return c.data.isSkeleton;
			}
			return false;
		}

		public static bool ColdProtected(Character c, float hot)
		{
			if (!Invincible(c) && !IsSkeleton(c) && !c.statusesLocked && !Has(c, (AfflictionType)5))
			{
				return hot > 0f;
			}
			return true;
		}

		public static bool HeatProtected(Character c, float cold)
		{
			if (Invincible(c) || IsSkeleton(c) || c.statusesLocked || cold > 0f)
			{
				return true;
			}
			if (Has(c, (AfflictionType)13) || ((Object)(object)c.data != (Object)null && c.data.wearingSunscreen))
			{
				return true;
			}
			Item val = (((Object)(object)c.data != (Object)null) ? c.data.currentItem : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (val.gliderHold)
			{
				return true;
			}
			Parasol componentInChildren = ((Component)val).GetComponentInChildren<Parasol>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return componentInChildren.isOpen;
			}
			return false;
		}

		public static bool StaminaBuffed(Character c)
		{
			if (!Has(c, (AfflictionType)1) && !Has(c, (AfflictionType)24) && (!((Object)(object)c.data != (Object)null) || !(c.data.timeInAntigrav > 0f)))
			{
				return RunSetting(() => Ascents.climbStaminaMultiplier) == 0f;
			}
			return true;
		}

		public static bool SpeedBuffed(Character c)
		{
			return Has(c, (AfflictionType)2);
		}

		public static bool Invincible(Character c)
		{
			if (!Has(c, (AfflictionType)16))
			{
				return Has(c, (AfflictionType)14);
			}
			return true;
		}

		public static bool HasSunscreen(Character c)
		{
			return Has(c, (AfflictionType)13);
		}

		public static bool JumpExempt(Character c)
		{
			//IL_007d: 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)
			if (HasBalloons(c) || Has(c, (AfflictionType)17) || Has(c, (AfflictionType)25) || Has(c, (AfflictionType)23))
			{
				return true;
			}
			if ((Object)(object)c.data != (Object)null && (c.data.lastBouncedTime + 3f > Time.time || c.data.sincePalJump < 3f || c.data.fallSeconds > 0f))
			{
				return true;
			}
			if (WearingJetpack(c) || NearTornado(c.Center, 30f))
			{
				return true;
			}
			return NearCannon(c.Center, 15f);
		}

		public static bool NearCannon(Vector3 p, float radius)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= _nextCannonScan)
			{
				_nextCannonScan = Time.time + 1f;
				_cannons = Object.FindObjectsByType<ScoutCannon>((FindObjectsSortMode)0);
			}
			ScoutCannon[] cannons = _cannons;
			foreach (ScoutCannon val in cannons)
			{
				if ((Object)(object)val != (Object)null)
				{
					Vector3 val2 = ((Component)val).transform.position - p;
					if (((Vector3)(ref val2)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool VanillaLaunch(Character c)
		{
			//IL_0009: 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)
			if (!FlightExempt(c) && !NearCannon(c.Center, 15f) && !BouncedRecently(c) && !NearBouncer(c.Center, 3f))
			{
				return Has(c, (AfflictionType)25);
			}
			return true;
		}

		public static bool InFrontOf(Character c, Vector3 p)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_00a6: 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)
			if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null)
			{
				return false;
			}
			Vector3 val = p - c.Center;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.5f || magnitude > 2.5f)
			{
				return false;
			}
			Vector3 val2 = c.data.lookDirection_Flat;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = c.data.lookDirection;
			}
			val2.y = 0f;
			val.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f || ((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return magnitude <= 1.5f;
			}
			return Vector3.Angle(val2, val) <= 50f;
		}

		internal static bool SpawnerFits(Spawner s, string itemName, uint pools)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_014e: Invalid comparison between Unknown and I4
			//IL_0116: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			if ((Object)(object)s.spawnedObjectPrefab != (Object)null)
			{
				flag = true;
				if (((Object)s.spawnedObjectPrefab).name == itemName)
				{
					return true;
				}
			}
			if ((Object)(object)s.spawns != (Object)null && s.spawns.items != null)
			{
				flag = true;
				foreach (SpawnEntry item in s.spawns.items)
				{
					if (item != null && (Object)(object)item.prefab != (Object)null && ((Object)item.prefab).name == itemName)
					{
						return true;
					}
				}
			}
			if ((Object)(object)s.fallbackSpawn != (Object)null)
			{
				flag = true;
				if (((Object)s.fallbackSpawn).name == itemName)
				{
					return true;
				}
			}
			if ((int)s.spawnPool != 0)
			{
				flag = true;
				if ((int)(s.spawnPool & pools) != 0)
				{
					return true;
				}
				if (ChaosItems() && (pools & 0x8000000) != 0)
				{
					return true;
				}
			}
			if (s.heightBasedSpawnPools != null)
			{
				foreach (HeightBasedSpawnListEntry heightBasedSpawnPool in s.heightBasedSpawnPools)
				{
					if (heightBasedSpawnPool != null && (int)heightBasedSpawnPool.spawnPool != 0)
					{
						flag = true;
						if ((int)(heightBasedSpawnPool.spawnPool & pools) != 0)
						{
							return true;
						}
					}
				}
			}
			if ((int)s.spawnMode == 3)
			{
				return true;
			}
			return !flag;
		}

		private static bool ChaosItems()
		{
			try
			{
				return RunSettings.GetValue((SETTINGTYPE)20010, false) == 1;
			}
			catch
			{
				return false;
			}
		}

		public static string SegmentName()
		{
			//IL_0013: 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)
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				return ((Object)(object)instance != (Object)null) ? ((object)instance.GetCurrentSegment()/*cast due to .constrained prefix*/).ToString() : null;
			}
			catch
			{
				return null;
			}
		}

		public static bool InVoid()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				return (Object)(object)instance != (Object)null && (int)instance.GetCurrentSegment() == 6;
			}
			catch
			{
				return false;
			}
		}

		public static bool GrabSpawnAllowed(PlayerRecord r, Character requester, string itemName, double now)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			if (r.GrabOutputsSeenAt.TryGetValue(itemName, out var value) && now - value <= 5.0)
			{
				return true;
			}
			if (now - r.GuidebookSeenAt <= 5.0)
			{
				return true;
			}
			return false;
		}

		public static bool InLobbyScene()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!(name == "Airport"))
			{
				return name == "Title";
			}
			return true;
		}

		public static bool NearSkeleton(Vector3 p, float radius)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			Skelleton[] array = Object.FindObjectsByType<Skelleton>((FindObjectsSortMode)0);
			foreach (Skelleton val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 val2 = (((Object)(object)val.hip != (Object)null) ? val.hip.position : ((Component)val).transform.position) - p;
					if (((Vector3)(ref val2)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool Has(Character c, AfflictionType type)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			CharacterAfflictions val = ((c.refs != null) ? c.refs.afflictions : null);
			Affliction val2 = default(Affliction);
			if ((Object)(object)val != (Object)null)
			{
				return val.HasAfflictionType(type, ref val2);
			}
			return false;
		}

		private static float RunSetting(Func<float> read)
		{
			try
			{
				return read();
			}
			catch
			{
				return 1f;
			}
		}

		public static bool CannibalismPossible(Character eater, Character victim)
		{
			//IL_0048: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)eater != (Object)null && (Object)(object)victim != (Object)null && (Object)(object)victim.data != (Object)null && victim.data.cannibalismPermitted && (victim.data.passedOut || victim.data.fullyPassedOut))
			{
				Vector3 val = eater.Center - victim.Center;
				return ((Vector3)(ref val)).sqrMagnitude <= 36f;
			}
			return false;
		}

		public static bool BeingHauled(Character c)
		{
			if ((Object)(object)c.data != (Object)null && c.data.isKinecmatic)
			{
				return true;
			}
			if (HeldByCreature(c))
			{
				return true;
			}
			if (Time.time >= _nextHaulScan)
			{
				_nextHaulScan = Time.time + 1f;
				_spiders = Object.FindObjectsByType<Spider>((FindObjectsSortMode)0);
				_hooks = Object.FindObjectsByType<RescueHook>((FindObjectsSortMode)0);
			}
			Spider[] spiders = _spiders;
			foreach (Spider val in spiders)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.targetPlayer == (Object)(object)c)
				{
					return true;
				}
			}
			RescueHook[] hooks = _hooks;
			foreach (RescueHook val2 in hooks)
			{
				if ((Object)(object)val2 != (Object)null && val2.isPulling && (Object)(object)val2.targetPlayer == (Object)(object)c)
				{
					return true;
				}
			}
			return false;
		}

		public static bool HeldByCreature(Character target)
		{
			if (target.refs != null && (Object)(object)target.refs.afflictions != (Object)null && target.refs.afflictions.GetCurrentStatus((STATUSTYPE)14) > 0f)
			{
				return true;
			}
			if (Time.time >= _nextCreatureScan)
			{
				_nextCreatureScan = Time.time + 1f;
				_flyTraps = Object.FindObjectsByType<VenusFlyTrap>((FindObjectsSortMode)0);
				_frogs = Object.FindObjectsByType<FrogTongue>((FindObjectsSortMode)0);
			}
			VenusFlyTrap[] flyTraps = _flyTraps;
			foreach (VenusFlyTrap val in flyTraps)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val._targetPlayer == (Object)(object)target)
				{
					return true;
				}
			}
			FrogTongue[] frogs = _frogs;
			foreach (FrogTongue val2 in frogs)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2._targetCharacter == (Object)(object)target)
				{
					return true;
				}
			}
			return false;
		}

		public static bool InRun()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return false;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (name != "Airport")
			{
				return name != "Title";
			}
			return false;
		}

		public static bool NearBouncer(Vector3 p, float radius)
		{
			//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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= _nextBouncerScan)
			{
				_nextBouncerScan = Time.time + 2f;
				List<Collider> list = new List<Collider>();
				CollisionModifier[] array = Object.FindObjectsByType<CollisionModifier>((FindObjectsSortMode)0);
				foreach (CollisionModifier val in array)
				{
					if (!((Object)(object)val == (Object)null) && !(val.knockback <= 0f) && val.preventFallDamageIfKnockback)
					{
						Collider component = ((Component)val).GetComponent<Collider>();
						if ((Object)(object)component != (Object)null)
						{
							list.Add(component);
						}
					}
				}
				_bouncers = list.ToArray();
			}
			Collider[] bouncers = _bouncers;
			foreach (Collider val2 in bouncers)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Bounds bounds = val2.bounds;
					Vector3 val3 = ((Bounds)(ref bounds)).ClosestPoint(p) - p;
					if (((Vector3)(ref val3)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool BouncedRecently(Character c)
		{
			if ((Object)(object)c.data != (Object)null)
			{
				return c.data.lastBouncedTime + 0.5f > Time.time;
			}
			return false;
		}

		private static bool NearTornado(Vector3 p, float radius)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= _nextTornadoScan)
			{
				_nextTornadoScan = Time.time + 1f;
				_tornadoes = Object.FindObjectsByType<Tornado>((FindObjectsSortMode)0);
			}
			Tornado[] tornadoes = _tornadoes;
			foreach (Tornado val in tornadoes)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 val2 = ((Component)val).transform.position - p;
					val2.y = 0f;
					if (((Vector3)(ref val2)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool NearAny<T>(Vector3 p, float radius) where T : Component
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			T[] array = Object.FindObjectsByType<T>((FindObjectsSortMode)0);
			foreach (T val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Vector3 val2 = ((Component)val).transform.position - p;
					if (((Vector3)(ref val2)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool NearSpawnPoint(Vector3 p, float radius)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			foreach (SpawnPoint allSpawnPoint in SpawnPoint.allSpawnPoints)
			{
				if ((Object)(object)allSpawnPoint != (Object)null)
				{
					Vector3 val = ((Component)allSpawnPoint).transform.position - p;
					if (((Vector3)(ref val)).sqrMagnitude <= radius * radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool OwnsThrownWarpItem(Player sender, Character target)
		{
			WarpOnThrow[] array = Object.FindObjectsByType<WarpOnThrow>((FindObjectsSortMode)0);
			foreach (WarpOnThrow val in array)
			{
				Item val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Item>() : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((MonoBehaviourPun)val2).photonView == (Object)null) && ((MonoBehaviourPun)val2).photonView.Owner != null && ((MonoBehaviourPun)val2).photonView.Owner.ActorNumber == sender.ActorNumber && (Object)(object)val2.lastThrownCharacter == (Object)(object)target)
				{
					return true;
				}
			}
			return false;
		}

		public static bool SpawnInHandAllowed(string itemName)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			if (itemName == RunSettings.GRAPPLE_MODE_ITEM)
			{
				return true;
			}
			SpawnItemInHand[] array = Object.FindObjectsByType<SpawnItemInHand>((FindObjectsSortMode)0);
			foreach (SpawnItemInHand val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.item != (Object)null && ((Object)((Component)val.item).gameObject).name == itemName)
				{
					return true;
				}
			}
			return false;
		}

		public static float SolidThickness(Vector3 a, Vector3 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//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_004f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.3f || magnitude > 25f)
			{
				return 0f;
			}
			Vector3 val2 = val / magnitude;
			int num = LayerMask.op_Implicit(HelperFunctions.terrainMapMask);
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(a, val2, ref val3, magnitude, num, (QueryTriggerInteraction)1))
			{
				return 0f;
			}
			RaycastHit val4 = default(RaycastHit);
			if (!Physics.Raycast(b, -val2, ref val4, magnitude, num, (QueryTriggerInteraction)1))
			{
				return 0f;
			}
			float num2 = magnitude - ((RaycastHit)(ref val3)).distance - ((RaycastHit)(ref val4)).distance;
			if (!(num2 > 0f))
			{
				return 0f;
			}
			return num2;
		}
	}
	internal static class EvidenceLog
	{
		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		private static StreamWriter _log;

		private static StreamWriter _csv;

		private static string _dir;

		private static string _stamp;

		public static string LogPath { get; private set; } = "";

		public static void Init()
		{
			try
			{
				_dir = Path.Combine(Paths.BepInExRootPath, "SummitWatch", "logs");
				Directory.CreateDirectory(_dir);
				_stamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss", Inv);
				LogPath = Path.Combine(_dir, _stamp + ".txt");
				_log = new StreamWriter(LogPath, append: true)
				{
					AutoFlush = true
				};
				Line("Summit Watch 0.1.4 session started");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Evidence log disabled: " + ex.Message));
			}
		}

		public static void Line(string text)
		{
			try
			{
				_log?.WriteLine(DateTime.Now.ToString("HH:mm:ss", Inv) + "  " + text);
			}
			catch
			{
			}
		}

		public static void Hit(string playerName, int actor, string userId, Hit h)
		{
			string text = (string.IsNullOrEmpty(userId) ? "" : (", id " + userId));
			string text2 = (h.Proof ? ", PROOF" : "");
			Line(string.Format("{0} (actor {1}{2}) [{3}{4}] {5} | w={6} {7}", playerName, actor, text, h.Detector, text2, h.Reason, h.Weight.ToString("0.00", Inv), h.Raw));
		}

		public static void Calibration(string playerName, int actor, Sample s)
		{
			try
			{
				if (_dir != null)
				{
					if (_csv == null)
					{
						_csv = new StreamWriter(Path.Combine(_dir, _stamp + "_calibration.csv"), append: true)
						{
							AutoFlush = true
						};
						_csv.WriteLine("time,actor,name,gap,x,y,z,vx,vy,vz,hspeed,grounded,climbing,rope,sprinting,stamina,max_stamina,extra_stamina,hunger,injury,down,flight_exempt,landing_exempt,in_run,warping,solid");
					}
					_csv.WriteLine(string.Join(",", s.Time.ToString("0.000", Inv), actor.ToString(Inv), "\"" + playerName.Replace("\"", "'") + "\"", F(s.PacketGap), F(s.X), F(s.Y), F(s.Z), F(s.VX), F(s.VY), F(s.VZ), F(s.HorizontalSpeed), B(s.Grounded), B(s.Climbing), B(s.Rope), B(s.Sprinting), F(s.Stamina), F(s.MaxStamina), F(s.ExtraStamina), F(s.Hunger), F(s.Injury), B(s.DownOrCarried), B(s.FlightExempt), B(s.LandingExempt), B(s.InRun), B(s.Warping), F(s.SolidThickness)));
				}
			}
			catch
			{
			}
		}

		public static void Close()
		{
			try
			{
				_log?.Dispose();
				_csv?.Dispose();
			}
			catch
			{
			}
			_log = null;
			_csv = null;
		}

		private static string F(float v)
		{
			return v.ToString("0.###", Inv);
		}

		private static string B(bool v)
		{
			if (!v)
			{
				return "0";
			}
			return "1";
		}
	}
	internal static class ItemCatalog
	{
		internal sealed class Entry
		{
			public uint Pools;

			public bool Produced;
		}

		private static Dictionary<string, Entry> _items;

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

		private static readonly Dictionary<Type, FieldInfo[]> FieldCache = new Dictionary<Type, FieldInfo[]>();

		public static bool TryGet(string name, out Entry entry, out bool producedInScene)
		{
			entry = null;
			producedInScene = SceneProduced.Contains(name);
			if (_items == null)
			{
				Build();
			}
			if (_items != null)
			{
				return _items.TryGetValue(name, out entry);
			}
			return false;
		}

		private static void Build()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance;
				if ((Object)(object)instance == (Object)null || instance.itemLookup == null || instance.itemLookup.Count == 0)
				{
					return;
				}
				Dictionary<string, Entry> dictionary = new Dictionary<string, Entry>();
				foreach (Item value2 in instance.itemLookup.Values)
				{
					if (!((Object)(object)value2 == (Object)null))
					{
						LootData component = ((Component)value2).GetComponent<LootData>();
						dictionary[((Object)((Component)value2).gameObject).name] = new Entry
						{
							Pools = (((Object)(object)component != (Object)null) ? ((uint)(int)component.spawnLocations) : 0u)
						};
					}
				}
				foreach (Item value3 in instance.itemLookup.Values)
				{
					if ((Object)(object)value3 == (Object)null)
					{
						continue;
					}
					HashSet<string> hashSet = new HashSet<string>();
					MonoBehaviour[] componentsInChildren = ((Component)value3).GetComponentsInChildren<MonoBehaviour>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						Collect(componentsInChildren[i], hashSet, 0);
					}
					hashSet.Remove(((Object)((Component)value3).gameObject).name);
					foreach (string item in hashSet)
					{
						if (dictionary.TryGetValue(item, out var value))
						{
							value.Produced = true;
						}
					}
				}
				_items = dictionary;
				Plugin.Log.LogInfo((object)$"Item catalog: {dictionary.Count} items");
			}
			catch (Exception e)
			{
				Plugin.LogOnce("ItemCatalog.Build", e);
			}
		}

		public static void ScanScene()
		{
			try
			{
				SceneProduced.Clear();
				Type[] array = new Type[5]
				{
					typeof(Spawner),
					typeof(SingleItemSpawner),
					typeof(Breakable),
					typeof(CloudFungus),
					typeof(SpawnList)
				};
				for (int i = 0; i < array.Length; i++)
				{
					Object[] array2 = Object.FindObjectsByType(array[i], (FindObjectsSortMode)0);
					for (int j = 0; j < array2.Length; j++)
					{
						Collect(array2[j], SceneProduced, 0);
					}
				}
				FakeItem[] array3 = Object.FindObjectsByType<FakeItem>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				for (int i = 0; i < array3.Length; i++)
				{
					Collect(array3[i], SceneProduced, 0);
				}
				array = new Type[3]
				{
					typeof(Bugfix),
					typeof(ScoutStatue),
					typeof(GuidebookPageCollection)
				};
				for (int i = 0; i < array.Length; i++)
				{
					Object[] array2 = Resources.FindObjectsOfTypeAll(array[i]);
					for (int j = 0; j < array2.Length; j++)
					{
						Collect(array2[j], SceneProduced, 0);
					}
				}
			}
			catch (Exception e)
			{
				Plugin.LogOnce("ItemCatalog.ScanScene", e);
			}
		}

		private static void Collect(object o, HashSet<string> into, int depth)
		{
			if (o == null || depth > 3)
			{
				return;
			}
			FieldInfo[] array = Fields(o.GetType());
			foreach (FieldInfo fieldInfo in array)
			{
				object value;
				try
				{
					value = fieldInfo.GetValue(o);
				}
				catch
				{
					continue;
				}
				AddRef(value, into, depth);
			}
		}

		private static void AddRef(object v, HashSet<string> into, int depth)
		{
			if (v == null)
			{
				return;
			}
			Item val = (Item)((v is Item) ? v : null);
			if (val == null)
			{
				GameObject val2 = (GameObject)((v is GameObject) ? v : null);
				if (val2 == null)
				{
					if (v is Object || v is string)
					{
						return;
					}
					if (v is IEnumerable enumerable)
					{
						if (depth > 3)
						{
							return;
						}
						try
						{
							foreach (object item in enumerable)
							{
								AddRef(item, into, depth + 1);
							}
							return;
						}
						catch
						{
							return;
						}
					}
					if (v.GetType().IsClass)
					{
						Collect(v, into, depth + 1);
					}
				}
				else if ((Object)(object)val2 != (Object)null && (Object)(object)val2.GetComponent<Item>() != (Object)null)
				{
					into.Add(((Object)val2).name);
				}
			}
			else if ((Object)(object)val != (Object)null)
			{
				into.Add(((Object)((Component)val).gameObject).name);
			}
		}

		private static FieldInfo[] Fields(Type t)
		{
			if (FieldCache.TryGetValue(t, out var value))
			{
				return value;
			}
			List<FieldInfo> list = new List<FieldInfo>();
			Type type = t;
			while (type != null && type != typeof(MonoBehaviour) && type != typeof(object))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					Type fieldType = fieldInfo.FieldType;
					if (!fieldType.IsPrimitive && !fieldType.IsEnum && !(fieldType == typeof(string)) && !fieldType.IsPointer && !fieldType.IsValueType)
					{
						list.Add(fieldInfo);
					}
				}
				type = type.BaseType;
			}
			FieldInfo[] array = list.ToArray();
			FieldCache[t] = array;
			return array;
		}
	}
	public enum OverlayCorner
	{
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight
	}
	internal sealed class MiniOverlay
	{
		private struct Line
		{
			public string Name;

			public string Value;

			public Color Color;
		}

		private const float Width = 300f;

		private const float LineHeight = 20f;

		private const float Pad = 8f;

		private readonly List<Line> _lines = new List<Line>();

		private int _more;

		private double _nextRefresh;

		private GUIStyle _name;

		private GUIStyle _value;

		private GUIStyle _back;

		private float _opacity = -1f;

		public void Draw(Watch w, double now)
		{
			//IL_00a8: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: 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_026d: 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_0248: Unknown result type (might be due to invalid IL or missing references)
			if (now >= _nextRefresh)
			{
				_nextRefresh = now + 0.5;
				Refresh(w, now);
			}
			EnsureStyles();
			int num = Mathf.Max(1, _lines.Count) + ((_more > 0) ? 1 : 0);
			float num2 = 16f + 20f * (float)(num + 1);
			OverlayCorner value = SwConfig.OverlayCornerSetting.Value;
			float num3 = ((value == OverlayCorner.TopLeft || value == OverlayCorner.BottomLeft) ? 16f : ((float)Screen.width - 300f - 16f));
			float num4 = ((value == OverlayCorner.TopLeft || value == OverlayCorner.TopRight) ? 16f : ((float)Screen.height - num2 - 16f));
			GUI.Box(new Rect(num3, num4, 300f, num2), GUIContent.none, _back);
			float num5 = num4 + 8f;
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Color.white;
			GUI.Label(new Rect(num3 + 8f, num5, 284f, 20f), "Summit Watch" + (SwConfig.Passive ? "  · mod-friendly" : "") + "  (" + SwConfig.PanelKeyName + ")", _value);
			num5 += 20f;
			if (_lines.Count == 0)
			{
				GUI.contentColor = Styles.BandColor(Band.Clean);
				GUI.Label(new Rect(num3 + 8f, num5, 284f, 20f), "No other scouts yet", _name);
			}
			foreach (Line line in _lines)
			{
				GUI.contentColor = line.Color;
				GUI.Label(new Rect(num3 + 8f, num5, 165f, 20f), line.Name, _name);
				GUI.Label(new Rect(num3 + 135f, num5, 157f, 20f), line.Value, _value);
				num5 += 20f;
			}
			if (_more > 0)
			{
				GUI.contentColor = Styles.BandColor(Band.Clean);
				GUI.Label(new Rect(num3 + 8f, num5, 284f, 20f), $"+{_more} more", _name);
			}
			GUI.contentColor = contentColor;
		}

		private void Refresh(Watch w, double now)
		{
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			_lines.Clear();
			var list = (from r in w.Records.Values
				select new
				{
					r = r,
					res = r.Evaluate(now)
				} into x
				orderby x.res.Confirmed descending, x.res.Percent descending
				select x).ToList();
			int count = Mathf.Max(1, SwConfig.OverlayMaxLines.Value);
			foreach (var item in list.Take(count))
			{
				_lines.Add(new Line
				{
					Name = MiniLine.Name(item.r.Name, 18),
					Value = MiniLine.Value(item.res, item.r.Role, w.IsContained(item.r.Actor), w.IsFlightLocked(item.r)),
					Color = (Color)((item.r.Trusted && !item.res.Confirmed) ? new Color(0.55f, 0.85f, 1f) : Styles.BandColor(item.res.Band))
				});
			}
			_more = list.Count - _lines.Count;
		}

		private void EnsureStyles()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			Styles.Ensure();
			float num = Mathf.Clamp01(SwConfig.OverlayOpacity.Value);
			if (_back == null || !Mathf.Approximately(num, _opacity))
			{
				_opacity = num;
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, new Color(0.06f, 0.07f, 0.1f, num));
				val.Apply();
				_back = new GUIStyle(GUI.skin.box);
				_back.normal.background = val;
				_name = new GUIStyle(Styles.Label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1,
					wordWrap = false,
					clipping = (TextClipping)1
				};
				_value = new GUIStyle(_name)
				{
					alignment = (TextAnchor)2
				};
			}
		}
	}
	internal sealed class Panel
	{
		private Rect _rect = new Rect(40f, 80f, 720f, 520f);

		private Vector2 _scroll;

		public void Draw(Watch w)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_004f: 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)
			Styles.Ensure();
			_rect = GUILayout.Window(1398227284, _rect, (WindowFunction)delegate
			{
				DrawWindow(w);
			}, "Summit Watch  (" + SwConfig.PanelKeyName + " to close)", Styles.Window, Array.Empty<GUILayoutOption>());
		}

		private void DrawWindow(Watch w)
		{
			//IL_01a2: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
			double now = Watch.Now;
			List<KeyValuePair<PlayerRecord, ScoreResult>> list = (from r in w.Records.Values
				select new KeyValuePair<PlayerRecord, ScoreResult>(r, r.Evaluate(now)) into x
				orderby x.Value.Confirmed descending, x.Value.Percent descending
				select x).ToList();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(HostLine(w), Styles.Small, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			bool passive = SwConfig.Passive;
			if (GUILayout.Button(passive ? "Mod-friendly: ON" : "Mod-friendly: off", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
			{
				w.SetModFriendly(!passive);
			}
			if (Watch.IAmHost && PhotonNetwork.InRoom)
			{
				bool value = SwConfig.NoKicking.Value;
				if (GUILayout.Button(value ? "Kicking: OFF" : "Kicking: on", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
				{
					w.SetNoKicking(!value);
				}
				bool value2 = SwConfig.GroundFlyers.Value;
				if (GUILayout.Button(value2 ? "Ground flyers: on" : "Ground flyers: OFF", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
				{
					w.SetGroundFlyers(!value2);
				}
			}
			else if (w.KicksBlockedHere)
			{
				GUILayout.Label("Host rule: no kicking", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndHorizontal();
			_scroll = GUILayout.BeginScrollView(_scroll, Array.Empty<GUILayoutOption>());
			if (list.Count == 0)
			{
				GUILayout.Label("No other scouts in this lobby yet.", Styles.Label, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Click a name for their profile.", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			List<PlayerRecord> list2 = new List<PlayerRecord>();
			foreach (KeyValuePair<PlayerRecord, ScoreResult> item in list)
			{
				if (item.Key.Trusted)
				{
					list2.Add(item.Key);
				}
				else
				{
					DrawRow(w, item.Key, item.Value, now);
				}
			}
			if (list2.Count > 0)
			{
				GUILayout.Space(10f);
				GUILayout.Label("Trusted by the host (still logged)", Styles.Header, Array.Empty<GUILayoutOption>());
				foreach (PlayerRecord item2 in list2)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					if (GUILayout.Button(item2.Name, Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
					{
						if (w.Profile.Actor == item2.Actor)
						{
							w.Profile.Close();
						}
						else
						{
							w.Profile.Open(item2.Actor);
						}
					}
					GUILayout.Label(Roles.Label(item2.Role), Styles.Small, Array.Empty<GUILayoutOption>());
					GUILayout.EndHorizontal();
				}
			}
			if ((Watch.IAmHost || w.MyRole == Role.Bypass) && w.KickedThisSession.Count > 0)
			{
				GUILayout.Space(10f);
				GUILayout.Label("Kicked this session", Styles.Header, Array.Empty<GUILayoutOption>());
				foreach (Watch.KickedEntry item3 in w.KickedThisSession)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label(item3.Name, Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
					GUILayout.Label("by " + item3.By + ", " + Ago(now - item3.Time), Styles.Small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
					string text = w.UnkickBlockedReason(item3);
					GUI.enabled = text == null;
					if (GUILayout.Button("Unkick", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
					{
						w.Unkick(item3);
					}
					GUI.enabled = true;
					GUILayout.EndHorizontal();
					if (text != null)
					{
						GUILayout.Label("    " + text, Styles.Small, Array.Empty<GUILayoutOption>());
					}
				}
				GUILayout.Label("Unkicking lets them back in; they have to rejoin themselves.", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool value3 = SwConfig.ShowLogPath.Value;
			GUILayout.Label(value3 ? ("Evidence log: " + EvidenceLog.LogPath) : "Evidence log: path hidden", Styles.Small, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button(value3 ? "Hide path" : "Show path", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				SwConfig.ShowLogPath.Value = !value3;
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		private void DrawRow(Watch w, PlayerRecord r, ScoreResult res, double now)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			bool flag = w.Profile.Actor == r.Actor;
			Color contentColor = GUI.contentColor;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.contentColor = ((res.Band == Band.Clean) ? Styles.BandColor(Band.Clean) : Color.white);
			if (GUILayout.Button((flag ? "> " : "") + r.Name, Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
			{
				if (flag)
				{
					w.Profile.Close();
				}
				else
				{
					w.Profile.Open(r.Actor);
				}
			}
			GUI.contentColor = Styles.BandColor(res.Band);
			GUILayout.Label(res.Confirmed ? "CONFIRMED" : (res.Percent + "%  " + BandLabel(res.Band)), Styles.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
			GUI.contentColor = contentColor;
			GUI.enabled = res.Band >= Band.Watch;
			if (GUILayout.Button("Warn lobby", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				Warnings.Send(r, res);
			}
			GUI.enabled = true;
			CharacterData val = (((Object)(object)r.Character != (Object)null) ? r.Character.data : null);
			if ((Object)(object)val != (Object)null && GUILayout.Button(val.isMuted ? "Unmute" : "Mute", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(75f) }))
			{
				val.isMuted = !val.isMuted;
			}
			if (w.IsContained(r.Actor))
			{
				GUI.contentColor = Styles.BandColor(Band.Confirmed);
				GUILayout.Label("IGNORED KICK", Styles.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				GUI.contentColor = contentColor;
			}
			else if (w.IsFlightLocked(r))
			{
				GUI.contentColor = Styles.BandColor(Band.VeryLikely);
				GUILayout.Label("FLIGHT LOCK", Styles.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				GUI.contentColor = contentColor;
			}
			GUILayout.EndHorizontal();
			string text = Summary(res);
			if (text.Length > 0)
			{
				GUILayout.Label("    " + text, Styles.Small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(6f);
		}

		private static string HostLine(Watch w)
		{
			if (!PhotonNetwork.InRoom)
			{
				return "Not in a lobby.";
			}
			if (Watch.IAmHost)
			{
				return "You're the host: you set who is trusted (in a player's profile) and can kick.";
			}
			Player masterClient = PhotonNetwork.MasterClient;
			string text = WarningText.SanitizeName((masterClient != null) ? masterClient.NickName : null);
			if (!w.HostHasMod)
			{
				return "Host: " + text + ", no Summit Watch: nobody is trusted and kicking is off.";
			}
			return "Host: " + text + " (Summit Watch).  Your role: " + Roles.Label(w.MyRole) + ".";
		}

		internal static void DetectorLine(string reliability, string name, float score, Color color, int count, string reason)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Space(24f);
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Styles.ReliabilityColor(reliability);
			GUILayout.Label(reliability, Styles.Small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			GUI.contentColor = contentColor;
			GUILayout.Label(name, Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			Styles.Bar(score, color);
			GUILayout.Label($" {score * 100f:0}%" + ((count > 1) ? $"  x{count}" : ""), Styles.Small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label(reason, Styles.Small, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
		}

		private static string Summary(ScoreResult res)
		{
			List<string> list = new List<string>();
			if (res.Confirmed)
			{
				list.Add(res.ProofHit.Reason);
			}
			foreach (DetectorScore item in res.Detectors.Take(res.Confirmed ? 1 : 2))
			{
				list.Add(item.Latest.Reason + ((item.Count > 1) ? $" ({item.Count}x)" : ""));
			}
			return string.Join("; ", list);
		}

		private static string Ago(double seconds)
		{
			if (!(seconds < 60.0))
			{
				return $"{seconds / 60.0:0}m ago";
			}
			return $"{seconds:0}s ago";
		}

		private static string BandLabel(Band b)
		{
			return b switch
			{
				Band.Watch => "Watch", 
				Band.Likely => "Likely", 
				Band.VeryLikely => "Very likely", 
				_ => "Clean", 
			};
		}
	}
	internal sealed class PlayerRecord
	{
		public readonly int Actor;

		public string Name = "Unknown scout";

		public string UserId;

		public Character Character;

		public readonly PlayerScore Score = new PlayerScore();

		public readonly HitGate Gate = new HitGate();

		public readonly VoiceTap Voice = new VoiceTap();

		public readonly StatusPeerDetector Peers = new StatusPeerDetector(SwConfig.WeightFor("ColdHeat"));

		public readonly List<ISampleDetector> Detectors;

		public readonly SpawnLedger Spared = new SpawnLedger();

		public double LastPacketTime = double.NaN;

		public Vector3 LastHip;

		public bool HasLastHip;

		public double WarpItemSeenAt = double.NegativeInfinity;

		public double EffigySeenAt = double.NegativeInfinity;

		public double BookSeenAt = double.NegativeInfinity;

		public double LastOwnJumpAt = double.NegativeInfinity;

		public double LastPalJumpAt = double.NegativeInfinity;

		public double LastKickAt = double.NegativeInfinity;

		public double BouncedAt = double.NegativeInfinity;

		public double LastFastAt = double.NegativeInfinity;

		public readonly SafeSpots GroundSpots = new SafeSpots(60.0);

		public double NextGroundSpot;

		public double GroundedAt = double.NegativeInfinity;

		public double GroundCheckAt;

		public Vector3 GroundCheckSpot;

		public float GroundCheckClosest = float.MaxValue;

		public int GroundCount;

		public readonly PendingRescue HostRescue = new PendingRescue();

		public double HostRescuedAt = double.NegativeInfinity;

		public int HostRescueCount;

		public readonly FlightLock FlightLock = new FlightLock(SwConfig.FlightLockFlags.Value, (double)SwConfig.FlightLockMinutes.Value * 60.0);

		public bool LockOverride;

		public double LockAirSince = double.NaN;

		public double LockPulledAt = double.NegativeInfinity;

		public double LockNotedAt = double.NegativeInfinity;

		public float LockStartY = float.NaN;

		public int LockPulls;

		public readonly FloatTimer Float = new FloatTimer();

		public double RescuedAt = double.NegativeInfinity;

		public double GuidebookSeenAt = double.NegativeInfinity;

		public double CloneToolSeenAt = double.NegativeInfinity;

		public readonly Dictionary<string, double> GrabOutputsSeenAt = new Dictionary<string, double>();

		public readonly Dictionary<string, double> InventorySeenAt = new Dictionary<string, double>();

		public readonly Dictionary<string, double> InventorySince = new Dictionary<string, double>();

		public Band LastBand;

		public readonly double WatchingSince = Watch.Now;

		private int _evalFrame = -1;

		private ScoreResult _eval;

		public Role Role
		{
			get
			{
				if (!((Object)(object)Watch.Instance != (Object)null))
				{
					return Role.None;
				}
				return Watch.Instance.RoleOfId(UserId);
			}
		}

		public bool Trusted => Role != Role.None;

		public PlayerRecord(int actor)
		{
			Actor = actor;
			Detectors = new List<ISampleDetector>
			{
				new FlightDetector(SwConfig.FlightSeconds.Value, SwConfig.WeightFor("Flight")),
				new SpeedDetector(SwConfig.SpeedLimit.Value, 1f, SwConfig.WeightFor("Speed")),
				new TeleportDetector(SwConfig.TeleportDistance.Value, 0.5f, SwConfig.WeightFor("Teleport")),
				new NoclipDetector(SwConfig.NoclipThickness.Value, SwConfig.WeightFor("Noclip")),
				new StaminaDetector(SwConfig.StaminaWindow.Value, 0.05f, SwConfig.WeightFor("Stamina")),
				new HungerDetector(SwConfig.HungerWindow.Value, 0.005f, SwConfig.WeightFor("Hunger")),
				new LandingDetector(SwConfig.LandingFall.Value, 0.05f, 1.5, SwConfig.WeightFor("Landing")),
				new SuperJumpDetector(SwConfig.SuperJumpRise.Value, SwConfig.WeightFor("SuperJump")),
				new FlingDetector(SwConfig.TeleportDistance.Value, 0.5f, 8, 2.0, 10.0, SwConfig.WeightFor("Fling")),
				new GroundedInAirDetector(2.5f, 1.0, 10.0, SwConfig.WeightFor("GroundedInAir")),
				new GravityDetector(1.5, 0.6, 0.5f, 2f, 0.6, 5.0, SwConfig.WeightFor("DefyGravity"))
			};
		}

		public void ResetDetectors()
		{
			foreach (ISampleDetector detector in Detectors)
			{
				detector.Reset();
			}
			HasLastHip = false;
			LastPacketTime = double.NaN;
		}

		public ScoreResult Evaluate(double now)
		{
			int frameCount = Time.frameCount;
			if (_eval == null || frameCount != _evalFrame)
			{
				_eval = Score.Evaluate(now, SwConfig.HalfLifeSeconds.Value, SwConfig.CapFor);
				_evalFrame = frameCount;
			}
			return _eval;
		}
	}
	[BepInPlugin("summitwatch", "Summit Watch", "0.1.4")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "summitwatch";

		public const string Name = "Summit Watch";

		public const string Version = "0.1.4";

		internal static ManualLogSource Log;

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

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			SwConfig.Init(((BaseUnityPlugin)this).Config);
			EvidenceLog.Init();
			Application.quitting += EvidenceLog.Close;
			Warnings.Hook();
			Application.quitting += Warnings.Unhook;
			_harmony = new Harmony("summitwatch");
			_harmony.PatchAll();
			GameObject val = new GameObject("SummitWatch")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<Watch>();
			Log.LogInfo((object)("Summit Watch v0.1.4 loaded. Evidence log: " + EvidenceLog.LogPath));
		}

		internal static void LogOnce(string where, Exception e)
		{
			if (Logged.Add(where + ":" + e.GetType().Name))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)(where + ": " + e));
				}
			}
		}
	}
	internal sealed class ProfileWindow
	{
		private const float LineHeight = 22f;

		private const float ListHeight = 300f;

		private Rect _rect = new Rect((float)(Screen.width - 700), 80f, 660f, 720f);

		private Vector2 _scroll;

		private int _confirmKick = -1;

		private double _confirmKickUntil;

		public int Actor { get; private set; } = -1;

		public void Open(int actor)
		{
			//IL_000a: 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)
			if (Actor != actor)
			{
				_scroll = Vector2.zero;
			}
			Actor = actor;
		}

		public void Close()
		{
			Actor = -1;
		}

		public void Draw(Watch w)
		{
			//IL_004f: 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_0084: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if (Actor < 0)
			{
				return;
			}
			if (!w.Records.TryGetValue(Actor, out var r))
			{
				Close();
				return;
			}
			Styles.Ensure();
			_rect = GUILayout.Window(1398231122, _rect, (WindowFunction)delegate
			{
				DrawWindow(w, r);
			}, "Profile: " + r.Name, Styles.Window, Array.Empty<GUILayoutOption>());
		}

		private void DrawWindow(Watch w, PlayerRecord r)
		{
			//IL_0018: 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_0024: 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_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_063f: Unknown result type (might be due to invalid IL or missing references)
			double now = Watch.Now;
			ScoreResult scoreResult = r.Evaluate(now);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Styles.BandColor(scoreResult.Band);
			GUILayout.Label(scoreResult.Confirmed ? "CONFIRMED cheating" : $"{scoreResult.Percent}%  {BandLabel(scoreResult.Band)}", Styles.Big, Array.Empty<GUILayoutOption>());
			GUI.contentColor = contentColor;
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("X", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }))
			{
				Close();
			}
			GUILayout.EndHorizontal();
			if (scoreResult.NeedsCorroboration)
			{
				GUILayout.Label("Held at 59%: only one kind of evidence so far. A second, independent signal is needed to reach Likely.", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string text = (string.IsNullOrEmpty(r.UserId) ? "unknown" : r.UserId);
			GUILayout.Label("Id: " + text, Styles.Label, Array.Empty<GUILayoutOption>());
			if (!string.IsNullOrEmpty(r.UserId) && GUILayout.Button("Copy ID", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				GUIUtility.systemCopyBuffer = r.UserId;
			}
			GUILayout.Label("Actor " + r.Actor, Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			Player val = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.GetPlayer(r.Actor, false) : null);
			if (val != null && val.IsMasterClient)
			{
				GUI.contentColor = Styles.BandColor(Band.Watch);
				GUILayout.Label("HOST", Styles.Header, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
				GUI.contentColor = contentColor;
			}
			GUILayout.EndHorizontal();
			GUILayout.Label(LiveStatus(r) + $"   ·   watching {Duration(now - r.WatchingSince)}   ·   {r.Score.Hits.Count} offenses", Styles.Small, Array.Empty<GUILayoutOption>());
			GUILayout.Space(4f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.enabled = scoreResult.Band >= Band.Watch && !r.Trusted;
			if (GUILayout.Button("Warn lobby", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				Warnings.Send(r, scoreResult);
			}
			GUI.enabled = true;
			CharacterData val2 = (((Object)(object)r.Character != (Object)null) ? r.Character.data : null);
			if ((Object)(object)val2 != (Object)null && GUILayout.Button(val2.isMuted ? "Unmute" : "Mute", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				val2.isMuted = !val2.isMuted;
			}
			if (GUILayout.Button("Copy report", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				GUIUtility.systemCopyBuffer = ReportText.Build(r.Name, r.UserId, r.Actor, scoreResult, r.Score.Hits, Clock);
				EvidenceLog.Line($"Report copied for {r.Name} (actor {r.Actor})");
			}
			GUILayout.EndHorizontal();
			DrawRoleAndKick(w, r, now);
			if (Watch.IAmHost && w.IsFlightLocked(r))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Flight lock: pulled down on every takeoff (caught flying repeatedly).", Styles.Small, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Unlock", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
				{
					w.UnlockFlight(r);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			GUILayout.Label("Evidence by detector", Styles.Header, Array.Empty<GUILayoutOption>());
			if (scoreResult.Confirmed)
			{
				Panel.DetectorLine("Proof", DetectorIds.DisplayName(scoreResult.ProofHit.Detector), 1f, Styles.BandColor(Band.Confirmed), 1, scoreResult.ProofHit.Reason);
			}
			foreach (DetectorScore detector in scoreResult.Detectors)
			{
				string reliability = DetectorIds.Reliability(detector.Detector);
				Panel.DetectorLine(reliability, DetectorIds.DisplayName(detector.Detector), detector.Score, Styles.ReliabilityColor(reliability), detector.Count, detector.Latest.Reason);
			}
			if (!scoreResult.Confirmed && scoreResult.Detectors.Count == 0)
			{
				GUILayout.Label("      No current evidence.", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(8f);
			IReadOnlyList<Hit> hits = r.Score.Hits;
			GUILayout.Label($"All offenses ({hits.Count}, newest first)", Styles.Header, Array.Empty<GUILayoutOption>());
			_scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(300f) });
			if (hits.Count == 0)
			{
				GUILayout.Label("None.", Styles.Small, Array.Empty<GUILayoutOption>());
			}
			else
			{
				int num = Mathf.Clamp((int)(_scroll.y / 22f), 0, hits.Count - 1);
				int num2 = Mathf.Min(hits.Count - num, 15);
				GUILayout.Space((float)num * 22f);
				for (int i = num; i < num + num2; i++)
				{
					Hit hit = hits[hits.Count - 1 - i];
					string text2 = DetectorIds.Reliability(hit.Detector);
					GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) });
					GUILayout.Label(Clock(hit.Time) + " · " + Ago(now - hit.Time), Styles.SmallNoWrap, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
					GUI.contentColor = Styles.ReliabilityColor(text2);
					GUILayout.Label(text2, Styles.SmallNoWrap, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(56f) });
					GUI.contentColor = contentColor;
					GUILayout.Label(DetectorIds.DisplayName(hit.Detector) + (hit.Proof ? " (PROOF)" : "") + ": " + hit.Reason, Styles.SmallNoWrap, Array.Empty<GUILayoutOption>());
					GUILayout.EndHorizontal();
				}
				GUILayout.Space((float)(hits.Count - num - num2) * 22f);
			}
			GUILayout.EndScrollView();
			GUI.DragWindow();
		}

		private void DrawRoleAndKick(Watch w, PlayerRecord r, double now)
		{
			GUILayout.Space(4f);
			if (!Watch.IAmHost)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Saved for when you host:", Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) });
				RolePicker(w, r, w.SavedRoleOf(r.UserId));
				GUILayout.EndHorizontal();
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (Watch.IAmHost)
			{
				GUILayout.Label("Role:", Styles.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) });
				RolePicker(w, r, r.Role);
			}
			else
			{
				string text = (w.HostHasMod ? (Roles.Label(r.Role) + " (set by the host)") : "Not trusted (the host doesn't have Summit Watch)");
				GUILayout.Label("Role here: " + text, Styles.Label, Array.Empty<GUILayoutOption>());
			}
			GUILayout.FlexibleSpace();
			if ((Watch.IAmHost || w.MyRole == Role.Bypass) && w.IsContained(r.Actor))
			{
				Watch.KickedEntry e = w.KickedEntryFor(r);
				string text2 = w.UnkickBlockedReason(e);
				GUI.enabled = text2 == null;
				if (GUILayout.Button("Unkick", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
				{
					w.Unkick(e);
				}
				GUI.enabled = true;
				GUILayout.EndHorizontal();
				if (text2 != null)
				{
					GUILayout.Label("Unkick: " + text2, Styles.Small, Array.Empty<GUILayoutOption>());
				}
			}
			else if (Watch.IAmHost || w.MyRole == Role.Bypass)
			{
				string text3 = w.KickBlockedReason(r);
				bool flag = _confirmKick == r.Actor && now <= _confirmKickUntil;
				GUI.enabled = text3 == null;
				if (GUILayout.Button(flag ? "Click again to kick" : "Kick", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
				{
					if (flag)
					{
						_confirmKick = -1;
						w.Kick(r);
					}
					else
					{
						_confirmKick = r.Actor;
						_confirmKickUntil = now + 3.0;
					}
				}
				GUI.enabled = true;
				GUILayout.EndHorizontal();
				if (text3 != null)
				{
					GUILayout.Label("Kick: " + text3, Styles.Small, Array.Empty<GUILayoutOption>());
				}
			}
			else if (w.MyRole == Role.Trusted)
			{
				string text4 = w.RequestBlockedReason(r, now);
				GUI.enabled = text4 == null;
				if (GUILayout.Button("Request kick", Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }))
				{
					w.RequestKick(r);
				}
				GUI.enabled = true;
				GUILayout.EndHorizontal();
				if (text4 != null)
				{
					GUILayout.Label("Request kick: " + text4, Styles.Small, Array.Empty<GUILayoutOption>());
				}
			}
			else
			{
				GUILayout.EndHorizontal();
			}
		}

		private static void RolePicker(Watch w, PlayerRecord r, Role current)
		{
			if (string.IsNullOrEmpty(r.UserId))
			{
				GUILayout.Label("no id yet", Styles.Small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) });
				return;
			}
			Role[] array = new Role[3]
			{
				Role.None,
				Role.Trusted,
				Role.Bypass
			};
			foreach (Role role in array)
			{
				GUI.enabled = current != role;
				if (GUILayout.Button(((current == role) ? "> " : "") + Roles.Label(role), Styles.Button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(118f) }))
				{
					w.SetRole(r, role);
				}
			}
			GUI.enabled = true;
		}

		private static string LiveStatus(PlayerRecord r)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			Character character = r.Character;
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return "No scout right now";
			}
			string text = (character.data.dead ? "Dead" : ((character.data.fullyPassedOut || character.data.passedOut) ? "Passed out" : "Alive"));
			string text2 = (((Object)(object)Character.localCharacter != (Object)null) ? $"{Vector3.Distance(Character.localCharacter.Center, character.Center):0} m away" : "distance unknown");
			Item currentItem = character.data.currentItem;
			string text3 = (((Object)(object)currentItem != (Object)null) ? ("holding " + WarningText.SanitizeName(((Object)((Component)currentItem).gameObject).name.Replace("(Clone)", ""))) : "empty hands");
			return text + "   ·   " + text2 + "   ·   " + text3;
		}

		private static string Clock(double hitTime)
		{
			return DateTime.Now.AddSeconds(hitTime - Watch.Now).ToString("HH:mm:ss", CultureInfo.InvariantCulture);
		}

		private static string Ago(double seconds)
		{
			if (!(seconds < 60.0))
			{
				if (!(seconds < 3600.0))
				{
					return $"{seconds / 3600.0:0.0}h ago";
				}
				return $"{seconds / 60.0:0}m ago";
			}
			return $"{seconds:0}s ago";
		}

		private static string Duration(double seconds)
		{
			if (!(seconds < 60.0))
			{
				if (!(seconds < 3600.0))
				{
					return $"{seconds / 3600.0:0.0}h";
				}
				return $"{seconds / 60.0:0}m";
			}
			return $"{seconds:0}s";
		}

		private static string BandLabel(Band b)
		{
			return b switch
			{
				Band.Watch => "Watch", 
				Band.Likely => "Likely", 
				Band.VeryLikely => "Very likely", 
				_ => "Clean", 
			};
		}
	}
	internal static class Styles
	{
		public static GUIStyle Window;

		public static GUIStyle Label;

		public static GUIStyle Small;

		public static GUIStyle SmallNoWrap;

		public static GUIStyle Button;

		public static GUIStyle Toast;

		public static GUIStyle Header;

		public static GUIStyle Big;

		public static Texture2D BarBack;

		public static Texture2D BarFill;

		public static void Ensure()
		{
			//IL_001c: 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_0036: 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_0045: 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_0058: Expected O, but got Unknown
			//IL_005d: Expected O, but got Unknown
			//IL_0087: 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_00af: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00e1: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_010b: 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_0118: 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_012b: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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_016b: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: 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_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: 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_0249: 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_025f: 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_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_0297: Expected O, but got Unknown
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			if (Window == null)
			{
				Texture2D background = Tex(new Color(0.06f, 0.07f, 0.1f, 0.97f));
				Window = new GUIStyle(GUI.skin.window)
				{
					fontSize = 17,
					fontStyle = (FontStyle)1,
					padding = new RectOffset(14, 14, 32, 12)
				};
				Window.normal.background = background;
				Window.onNormal.background = background;
				Window.normal.textColor = Color.white;
				Window.onNormal.textColor = Color.white;
				Label = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15,
					richText = false
				};
				Label.normal.textColor = new Color(0.96f, 0.96f, 0.96f);
				Header = new GUIStyle(Label)
				{
					fontStyle = (FontStyle)1
				};
				Small = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					wordWrap = true,
					richText = false
				};
				Small.normal.textColor = new Color(0.78f, 0.82f, 0.9f);
				SmallNoWrap = new GUIStyle(Small)
				{
					wordWrap = false,
					clipping = (TextClipping)1
				};
				Big = new GUIStyle(Label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1
				};
				Button = new GUIStyle(GUI.skin.button)
				{
					fontSize = 14
				};
				Button.normal.background = Tex(new Color(0.2f, 0.25f, 0.34f));
				Button.hover.background = Tex(new Color(0.3f, 0.37f, 0.5f));
				Button.active.background = Tex(new Color(0.14f, 0.18f, 0.25f));
				GUIStyleState normal = Button.normal;
				GUIStyleState hover = Button.hover;
				Color val = (Button.active.textColor = Color.white);
				Color textColor = (hover.textColor = val);
				normal.textColor = textColor;
				Toast = new GUIStyle(GUI.skin.box)
				{
					fontSize = 17,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4,
					wordWrap = true,
					padding = new RectOffset(12, 12, 8, 8)
				};
				Toast.normal.background = Tex(new Color(0.06f, 0.07f, 0.1f, 0.95f));
				Toast.normal.textColor = new Color(1f, 0.62f, 0.38f);
				BarBack = Tex(new Color(0.22f, 0.24f, 0.3f));
				BarFill = Tex(Color.white);
			}
		}

		public static Color BandColor(Band b)
		{
			//IL_0029: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(b switch
			{
				Band.Watch => new Color(1f, 0.86f, 0.3f), 
				Band.Likely => new Color(1f, 0.58f, 0.22f), 
				Band.VeryLikely => new Color(1f, 0.34f, 0.34f), 
				Band.Confirmed => new Color(1f, 0.36f, 0.86f), 
				_ => new Color(0.66f, 0.68f, 0.72f), 
			});
		}

		public static Color ReliabilityColor(string reliability)
		{
			//IL_0038: 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_0062: 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)
			return (Color)(reliability switch
			{
				"Proof" => new Color(1f, 0.36f, 0.86f), 
				"Strong" => new Color(1f, 0.45f, 0.4f), 
				"Medium" => new Color(1f, 0.78f, 0.35f), 
				_ => new Color(0.66f, 0.72f, 0.8f), 
			});
		}

		public static void Bar(float value, Color color, float width = 110f)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(width, 12f, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.Height(12f)
			});
			((Rect)(ref rect)).y = ((Rect)(ref rect)).y + 4f;
			GUI.DrawTexture(rect, (Texture)(object)BarBack);
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * Mathf.Clamp01(value), ((Rect)(ref rect)).height), (Texture)(object)BarFill);
			GUI.color = color2;
		}

		private static Texture2D Tex(Color c)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1)
			{
				hideFlags = (HideFlags)61
			};
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}
	}
	internal sealed class DetectorConfig
	{
		public ConfigEntry<bool> Enabled;

		public ConfigEntry<float> Weight;

		public ConfigEntry<float> Cap;
	}
	internal static class SwConfig
	{
		public static ConfigEntry<KeyboardShortcut> PanelShortcut;

		public static ConfigEntry<OverlayCorner> OverlayCornerSetting;

		public static ConfigEntry<float> OverlayOpacity;

		public static ConfigEntry<int> OverlayMaxLines;

		public static ConfigEntry<bool> ToastsEnabled;

		public static ConfigEntry<float> HalfLifeSeconds;

		public static ConfigEntry<bool> CalibrationMode;

		public static ConfigEntry<string> TrustedPlayers;

		public static ConfigEntry<bool> ShowLogPath;

		public static ConfigEntry<bool> ModFriendly;

		public static ConfigEntry<float> FlightSeconds;

		public static ConfigEntry<float> SpeedLimit;

		public static ConfigEntry<float> TeleportDistance;

		public static ConfigEntry<float> NoclipThickness;

		public static ConfigEntry<float> StaminaWindow;

		public static ConfigEntry<float> HungerWindow;

		public static ConfigEntry<float> LandingFall;

		public static ConfigEntry<float> SuperJumpRise;

		public static ConfigEntry<bool> FloodEnabled;

		public static ConfigEntry<int> FloodThreshold;

		public static ConfigEntry<float> FloodWindowSeconds;

		public static ConfigEntry<bool> FloodHostDelete;

		public static ConfigEntry<bool> FloodHideForMe;

		public static ConfigEntry<bool> CleanupEnabled;

		public static ConfigEntry<CleanupLevel> CleanupLevelSetting;

		public static ConfigEntry<bool> CleanupFromInventory;

		public static ConfigEntry<string> TrustRoles;

		public static ConfigEntry<bool> AutoKickConfirmed;

		public static ConfigEntry<bool> ShowKickRequests;

		public static ConfigEntry<bool> ContainIgnoredKicks;

		public static ConfigEntry<bool> AutoKickRejoinSpam;

		public static ConfigEntry<bool> NoKicking;

		public static ConfigEntry<bool> ApproveModKicks;

		public static ConfigEntry<bool> GroundFlyers;

		public static ConfigEntry<bool> HostRescue;

		public static ConfigEntry<bool> FlightLockEnabled;

		public static ConfigEntry<int> FlightLockFlags;

		public static ConfigEntry<float> FlightLockMinutes;

		public static ConfigEntry<int> RejoinLimit;

		public static ConfigEntry<float> RejoinWindowSeconds;

		public static ConfigEntry<bool> LagGuardEnabled;

		public static ConfigEntry<int> PileTrigger;

		public static ConfigEntry<int> PileKeep;

		public static ConfigEntry<int> ExplosionsPerSecond;

		public static ConfigEntry<bool> ShieldEnabled;

		public static ConfigEntry<bool> ShieldRestore;

		public static ConfigEntry<bool> AntiFling;

		public static ConfigEntry<float> AntiFlingSeconds;

		public static ConfigEntry<bool> FlingRescue;

		public static ConfigEntry<float> FlingRescueSideways;

		public static ConfigEntry<float> FlingRescueUpward;

		public static ConfigEntry<float> FlingRescueLookback;

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

		public static bool Passive
		{
			get
			{
				if (ModFriendly != null)
				{
					return ModFriendly.Value;
				}
				return false;
			}
		}

		public unsafe static string PanelKeyName
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: 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)
				KeyboardShortcut value = PanelShortcut.Value;
				return MiniLine.KeyName(((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString(), ((KeyboardShortcut)(ref value)).Modifiers.Select((KeyCode m) => ((object)(*(KeyCode*)(&m))/*cast due to .constrained prefix*/).ToString()));
			}
		}

		public static void Init(ConfigFile cfg)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PanelShortcut = cfg.Bind<KeyboardShortcut>("General", "PanelShortcut", new KeyboardShortcut((KeyCode)48, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Cycles Summit Watch: off -> mini overlay (names and %, game stays playable) -> full panel -> off. Either Ctrl key works.");
			OverlayCornerSetting = cfg.Bind<OverlayCorner>("Overlay", "Corner", OverlayCorner.TopLeft, "Where the mini overlay sits.");
			OverlayOpacity = cfg.Bind<float>("Overlay", "Opacity", 0.75f, "Mini overlay background opacity, 0-1.");
			OverlayMaxLines = cfg.Bind<int>("Overlay", "MaxLines", 12, "Most scouts listed in the mini overlay (highest % first).");
			ToastsEnabled = cfg.Bind<bool>("General", "ToastsEnabled", true, "Private corner alert when someone reaches Likely or Confirmed.");
			HalfLifeSeconds = cfg.Bind<float>("General", "HalfLifeSeconds", 180f, "Evidence counts half as much after this many seconds.");
			ModFriendly = cfg.Bind<bool>("General", "ModFriendly", false, "Pause everything Summit Watch does to your own game (shield, anti-fling, lag guard, hiding items, blocking players who ignored a kick) so it can't clash with your other mods. Detection, the %, warnings and host actions keep working. Panel button.");
			ShowLogPath = cfg.Bind<bool>("General", "ShowLogPath", false, "Show the evidence log's folder at the bottom of the panel. Off by default: the path can include your Windows username.");
			CalibrationMode = cfg.Bind<bool>("General", "CalibrationMode", false, "Write every received movement update to a CSV next to the evidence log, for tuning thresholds.");
			TrustedPlayers = cfg.Bind<string>("General", "TrustedPlayers", "", "Old name-only trust list. Each name here becomes Trusted (by id, in [Trust] Players) the first time that player is in your lobby.");
			TrustRoles = cfg.Bind<string>("Trust", "Players", "", "Your roles for when you host, as id|role|name;... (role 1 = Trusted, 2 = Shield bypass). Set them in a player's profile while hosting. Everyone with Summit Watch in your lobby uses this list; in someone else's lobby, theirs applies.");
			AutoKickConfirmed = cfg.Bind<bool>("Kick", "AutoKickConfirmed", false, "When you host: kick anyone (not trusted) the moment they're CONFIRMED cheating.");
			ShowKickRequests = cfg.Bind<bool>("Kick", "ShowKickRequests", true, "When you're host or shield bypass: show trusted players' kick requests with Kick / Ignore.");
			HostRescue = cfg.Bind<bool>("Shield", "HostRescue", true, "When you host: any (not trusted) player flung at an impossible speed is pulled back to where they last stood, even if they don't have Summit Watch. Skipped when their own Summit Watch already rescued them.");
			FlightLockEnabled = cfg.Bind<bool>("Kick", "FlightLock", true, "When you host: a not-trusted player caught flying FlightLockFlags times within FlightLockMinutes (or CONFIRMED) is pulled down on every takeoff, no more detection needed. Ends after FlightLockMinutes with no new flying flags, or with Unlock in their profile.");
			FlightLockFlags = cfg.Bind<int>("Kick", "FlightLockFlags", 2, "Flying flags (Flight, Defying gravity, Walking on air) that lock someone.");
			FlightLockMinutes = cfg.Bind<float>("Kick", "FlightLockMinutes", 10f, "Window for the flags, and how long a lock lasts without new ones.");
			GroundFlyers = cfg.Bind<bool>("Kick", "GroundFlyers", true, "When you host: a not-trusted player caught flying (hovering, or walking on air) is teleported back to where they last stood. Toggle it in the panel.");
			ApproveModKicks = cfg.Bind<bool>("Kick", "ApproveModKicks", true, "When you host: a shield-bypass player's kick becomes a Kick / Ignore prompt for you instead of happening at once, so a moderator gone rogue can't kick anyone without your click.");
			NoKicking = cfg.Bind<bool>("Kick", "NoKicking", false, "When you host: Summit Watch players in your lobby refuse in-game kicks from everyone but you and your shield-bypass players (players without Summit Watch can still be kicked). Toggle it in the panel.");
			AutoKickRejoinSpam = cfg.Bind<bool>("Kick", "AutoKickRejoinSpam", true, "Someone (not trusted) who joins and leaves more than RejoinLimit times within RejoinWindowSeconds is kicked the next time they join. Done by the host's game; shield-bypass players' Summit Watch asks the host's.");
			RejoinLimit = cfg.Bind<int>("Kick", "RejoinLimit", 3, "Join/leaves allowed inside the window; one more and they're kicked when they come back.");
			RejoinWindowSeconds = cfg.Bind<float>("Kick", "RejoinWindowSeconds", 120f, "Time window for RejoinLimit, in seconds.");
			ContainIgnoredKicks = cfg.Bind<bool>("Kick", "ContainIgnoredKicks", true, "A player who ignores a kick (cheat menu) is treated as gone: muted, their commands ignored, their new items removed.");
			FlightSeconds = cfg.Bind<float>("Thresholds", "FlightSeconds", 6f, "Seconds airborne without falling before Flight counts.");
			SpeedLimit = cfg.Bind<float>("Thresholds", "SpeedLimit", 12f, "Grounded horizontal speed (m/s) above which Speed counts. Tune from calibration data.");
			TeleportDistance = cfg.Bind<float>("Thresholds", "TeleportDistance", 25f, "Metres moved between two updates that counts as a teleport.");
			NoclipThickness = cfg.Bind<float>("Thresholds", "NoclipThickness", 0.6f, "Metres of solid terrain a move must pass through to count as noclip.");
			StaminaWindow = cfg.Bind<float>("Thresholds", "StaminaWindow", 15f, "Seconds of sprinting or climbing with no stamina drop before Endless stamina counts.");
			HungerWindow = cfg.Bind<float>("Thresholds", "HungerWindow", 480f, "Seconds in a run with no hunger rise before No hunger counts.");
			LandingFall = cfg.Bind<float>("Thresholds", "LandingFall", 30f, "Fall height (m) that should always hurt.");
			FloodEnabled = cfg.Bind<bool>("FloodGuard", "Enabled", true, "Remove mass-spawned items (one source dumping a pile) before the lobby crashes.");
			FloodThreshold = cfg.Bind<int>("FloodGuard", "Threshold", 12, "Unexplained items from one source, still in the world, that count as a flood.");
			FloodWindowSeconds = cfg.Bind<float>("FloodGuard", "WindowSeconds", 15f, "Time window for the threshold.");
			FloodHostDelete = cfg.Bind<bool>("FloodGuard", "HostDelete", true, "When you're host: delete flood items for everyone and drop that player's further spawn requests.");
			FloodHideForMe = cfg.Bind<bool>("FloodGuard", "HideForMe", true, "When you're not host: switch flood items off on your screen only (no model, physics or sound).");
			CleanupEnabled = cfg.Bind<bool>("SpawnCleanup", "Enabled", true, "Delete items Summit Watch judges as illegally spawned. Host: gone for everyone. Otherwise: gone from your screen.");
			CleanupLevelSetting = cfg.Bind<CleanupLevel>("SpawnCleanup", "Level", CleanupLevel.Everything, "Everything: any item flagged as spawned. Strong: only items that never appear naturally / later-biome items, and (as host) refuse unexplained spawn requests. Proof: only CONFIRMED impossible items. Floods are always removed.");
			CleanupFromInventory = cfg.Bind<bool>("SpawnCleanup", "FromInventory", true, "When you're host: also take an illegally spawned item out of the cheater's inventory/hands.");
			SuperJumpRise = cfg.Bind<float>("Thresholds", "SuperJumpRise", 4f, "Height (m) a jump from flat ground must rise to count as a super jump. Tune from calibration data.");
			AddDetector(cfg, "Puppeteer", 1f, 1f);
			AddDetector(cfg, "ForceSpam", 0.5f, 0.9f);
			AddDetector(cfg, "ForeignRevive", 0.4f, 0.7f);
			AddDetector(cfg, "SelfWarp", 0.5f, 0.85f);
			AddDetector(cfg, "ItemSpawn", 0.35f, 0.8f);
			AddDetector(cfg, "Flight", 0.15f, 0.85f);
			AddDetector(cfg, "Noclip", 0.3f, 0.8f);
			AddDetector(cfg, "Stamina", 0.5f, 0.8f);
			AddDetector(cfg, "Teleport", 0.35f, 0.75f);
			AddDetector(cfg, "Hunger", 0.5f, 0.7f);
			AddDetector(cfg, "Speed", 0.3f, 0.6f);
			AddDetector(cfg, "Landing", 0.4f, 0.6f);
			AddDetector(cfg, "Replay", 0.5f, 0.85f);
			AddDetector(cfg, "Earrape", 0.3f, 0.6f);
			AddDetector(cfg, "NotSpeech", 0.3f, 0.6f);
			AddDetector(cfg, "Nonstop", 0.25f, 0.5f);
			AddDetector(cfg, "HostKick", 1f, 1f);
			AddDetector(cfg, "HostTimer", 0.6f, 0.9f);
			AddDetector(cfg, "ColdHeat", 0.4f, 0.7f, enabledByDefault: false);
			AddDetector(cfg, "SuperJump", 0.25f, 0.5f);
			AddDetector(cfg, "SpawnRequest", 0.6f, 0.9f);
			AddDetector(cfg, "ImpossibleItem", 1f, 1f);
			AddDetector(cfg, "OutOfBiome", 0.6f, 0.85f);
			AddDetector(cfg, "UnnaturalItem", 0.6f, 0.85f);
			AddDetector(cfg, "ItemFlood", 0.7f, 0.9f);
			AddDetector(cfg, "ForcedMute", 1f, 1f);
			AddDetector(cfg, "ForceWin", 1f, 1f);
			AddDetector(cfg, "Fling", 0.6f, 0.85f);
			AddDetector(cfg, "HugeForce", 0.7f, 0.9f);
			AddDetector(cfg, "GroundedInAir", 0.6f, 0.85f);
			AddDetector(cfg, "DefyGravity", 0.5f, 0.85f);
			LagGuardEnabled = cfg.Bind<bool>("LagGuard", "Enabled", true, "Keep your game smooth when the flood guard doesn't catch a pile: spawned piles keep only their nearest items active and explosions are capped per second. Your screen only.");
			PileTrigger = cfg.Bind<int>("LagGuard", "PileTrigger", 15, "Spawned items of one type within 50 m of you before the pile cap kicks in.");
			PileKeep = cfg.Bind<int>("LagGuard", "PileKeep", 10, "How many of a capped pile (the nearest) stay active on your screen.");
			ExplosionsPerSecond = cfg.Bind<int>("LagGuard", "ExplosionsPerSecond", 3, "Most explosions your game plays per second; the rest of a burst is skipped on your screen.");
			ShieldEnabled = cfg.Bind<bool>("Shield", "Enabled", true, "Your game refuses kill, knock-out, teleport, petrify and stick commands aimed at your scout from other players' games (anyone but you and the host), bursts of shoves, and the mute/force-win commands the game never sends.");
			ShieldRestore = cfg.Bind<bool>("Shield", "FixOthersView", true, "After refusing a kill, knock-out or stick, tell the other games you're fine (the message your own game sends after a revive, wake-up or unstick).");
			AntiFling = cfg.Bind<bool>("Shield", "AntiFling", true, "When a player's body is flinging (jittering back and forth tens of metres), it stops colliding with yours.");
			AntiFlingSeconds = cfg.Bind<float>("Shield", "AntiFlingSeconds", 30f, "How long after the last fling their body stays unable to touch yours.");
			FlingRescue = cfg.Bind<bool>("Shield", "FlingRescue", true, "Last resort: if you're flung anyway (right after another player touched you), teleport back to where you last stood safely.");
			FlingRescueSideways = cfg.Bind<float>("Shield", "FlingRescueSideways", 40f, "Sideways speed (m/s) that counts as being flung. Falling never counts.");
			FlingRescueUpward = cfg.Bind<float>("Shield", "FlingRescueUpward", 35f, "Upward speed (m/s) that counts as being flung.");
			FlingRescueLookback = cfg.Bind<float>("Shield", "FlingRescueLookback", 0f, "Where a rescue sends you: 0 = the last place you stood before the fling began; e.g. 5 = where you stood 5 s before it.");
		}

		private static void AddDetector(ConfigFile cfg, string id, float weight, float cap, bool enabledByDefault = true)
		{
			string text = "Detector." + id;
			Detectors[id] = new DetectorConfig
			{
				Enabled = cfg.Bind<bool>(text, "Enabled", enabledByDefault, DetectorIds.DisplayName(id) + " detector on/off."),
				Weight = cfg.Bind<float>(text, "Weight", weight, "Strength of one hit, 0-1. (Puppeteer is proof and ignores this.)"),
				Cap = cfg.Bind<float>(text, "Cap", cap, "Most this detector alone can contribute, 0-1.")
			};
		}

		public static bool PanelPressed()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = PanelShortcut.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Held(modifier))
				{
					return false;
				}
			}
			return true;
		}

		private static bool Held(KeyCode k)
		{
			//IL_0000: 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_0024: Expected I4, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			switch (k - 303)
			{
			case 2:
			case 3:
				if (!Input.GetKey((KeyCode)306))
				{
					return Input.GetKey((KeyCode)305);
				}
				return true;
			case 0:
			case 1:
				if (!Input.GetKey((KeyCode)304))
				{
					return Input.GetKey((KeyCode)303);
				}
				return true;
			case 4:
			case 5:
				if (!Input.GetKey((KeyCode)308))
				{
					return Input.GetKey((KeyCode)307);
				}
				return true;
			default:
				return Input.GetKey(k);
			}
		}

		public static bool IsEnabled(string id)
		{
			if (Detectors.TryGetValue(id, out var value))
			{
				return value.Enabled.Value;
			}
			return false;
		}

		public static float WeightFor(string id)
		{
			if (!Detectors.TryGetValue(id, out var value))
			{
				return 0.3f;
			}
			return value.Weight.Value;
		}

		public static float CapFor(string id)
		{
			if (!Detectors.TryGetValue(id, out var value))
			{
				return 0.5f;
			}
			return value.Cap.Value;
		}
	}
	internal sealed class Toast
	{
		private string _text;

		private double _until;

		public void Show(string text, double now)
		{
			_text = text;
			_until = now + 5.0;
		}

		public void Draw(double now)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (_text != null && !(now > _until))
			{
				Styles.Ensure();
				GUI.Box(new Rect((float)(Screen.width - 460), 20f, 440f, 60f), "Summit Watch: " + _text, Styles.Toast);
			}
		}
	}
	internal sealed class VoiceTap
	{
		private const int MaxQueued = 500;

		private readonly ConcurrentQueue<KeyValuePair<float[], long>> _frames = new ConcurrentQueue<KeyValuePair<float[], long>>();

		private readonly List<IVoiceDetector> _detectors;

		private RemoteVoiceLink _link;

		private int _channels;

		private int _rate;

		public VoiceTap()
		{
			_detectors = new List<IVoiceDetector>
			{
				new ReplayDetector(1.5, 10.0, 0.95f, 0.05f, 20, SwConfig.WeightFor("Replay")),
				new EarrapeDetector(2f, 3.0, SwConfig.WeightFor("Earrape")),
				new NotSpeechDetector(8.0, 0.8f, 10f, SwConfig.WeightFor("NotSpeech")),
				new NonstopDetector(30.0, 0.9f, SwConfig.WeightFor("Nonstop"))
			};
		}

		public void Ensure(Character c)
		{
			Speaker val = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponentInChildren<Speaker>() : null);
			RemoteVoiceLink val2 = (((Object)(object)val != (Object)null) ? val.RemoteVoice : null);
			if (val2 != _link)
			{
				Detach();
				if (val2 != null)
				{
					_link = val2;
					_channels = ((VoiceInfo)(ref val2.VoiceInfo)).Channels;
					_rate = ((VoiceInfo)(ref val2.VoiceInfo)).SamplingRate;
					val2.FloatFrameDecoded += OnFrame;
				}
			}
		}

		public void Detach()
		{
			if (_link != null)
			{
				_link.FloatFrameDecoded -= OnFrame;
			}
			_link = null;
			KeyValuePair<float[], long> result;
			while (_frames.TryDequeue(out result))
			{
			}
		}

		private void OnFrame(FrameOut<float> f)
		{
			try
			{
				if (f != null && f.Buf != null && _frames.Count < 500)
				{
					_frames.Enqueue(new KeyValuePair<float[], long>((float[])f.Buf.Clone(), Stopwatch.GetTimestamp()));
				}
			}
			catch
			{
			}
		}

		public List<Hit> Drain(double now)
		{
			List<Hit> list = new List<Hit>();
			long timestamp = Stopwatch.GetTimestamp();
			KeyValuePair<float[], long> result;
			while (_frames.TryDequeue(out result))
			{
				double num = (double)(timestamp - result.Value) / (double)Stopwatch.Frequency;
				foreach (VoiceBlock item in VoiceAnalysis.ToBlocks(result.Key, _channels, _rate, now - num))
				{
					foreach (IVoiceDetector detector in _detectors)
					{
						Add(list, detector.Observe(item));
					}
				}
			}
			foreach (IVoiceDetector detector2 in _detectors)
			{
				Add(list, detector2.Tick(now));
			}
			return list;
		}

		private static void Add(List<Hit> hits, Hit h)
		{