Decompiled source of Lifeline v0.2.0

plugins/Lifeline/Lifeline.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Lc.Common;
using LethalCompanyInputUtils.Api;
using LethalNetworkAPI;
using Lifeline.Core;
using Lifeline.Patches;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("LethalCompanyInputUtils")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("thatumi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+860d7a915eb4bba7ae9e4014072e9ba7190ab209")]
[assembly: AssemblyProduct("Lifeline")]
[assembly: AssemblyTitle("Lifeline")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Lc.Common
{
	internal static class FontProvider
	{
		private static TMP_FontAsset? _hudFont;

		internal static TMP_FontAsset? Get()
		{
			if ((Object)(object)_hudFont != (Object)null)
			{
				return _hudFont;
			}
			TMP_FontAsset val = ReflectionGuard.Run("FontProvider.HUD", delegate
			{
				HUDManager instance = HUDManager.Instance;
				return (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.chatText != (Object)null)) ? null : ((TMP_Text)instance.chatText).font;
			}, null);
			if ((Object)(object)val != (Object)null)
			{
				_hudFont = val;
				return val;
			}
			TMP_FontAsset val2 = ReflectionGuard.Run("FontProvider.Default", () => TMP_Settings.defaultFontAsset, null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			TMP_FontAsset? obj = ReflectionGuard.Run("FontProvider.Any", () => Resources.FindObjectsOfTypeAll<TMP_FontAsset>().FirstOrDefault(), null);
			if ((Object)(object)obj == (Object)null)
			{
				Log.WarnOnce("FontProvider.none", "FontProvider: no TMP font available yet; text will use TMP defaults");
			}
			return obj;
		}

		internal static void Invalidate()
		{
			_hudFont = null;
		}
	}
	internal enum LogKind
	{
		Debug,
		Info,
		Warning,
		Error
	}
	internal static class Log
	{
		private static readonly object Gate = new object();

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

		private static Action<LogKind, string>? _sink;

		internal static bool DebugEnabled { get; set; }

		internal static void SetSink(Action<LogKind, string>? sink)
		{
			_sink = sink;
		}

		internal static void Debug(string message)
		{
			if (DebugEnabled)
			{
				Write(LogKind.Debug, message);
			}
		}

		internal static void Info(string message)
		{
			Write(LogKind.Info, message);
		}

		internal static void Warn(string message)
		{
			Write(LogKind.Warning, message);
		}

		internal static void Error(string message)
		{
			Write(LogKind.Error, message);
		}

		internal static bool WarnOnce(string key, string message)
		{
			if (!MarkOnce(key))
			{
				return false;
			}
			Write(LogKind.Warning, message);
			return true;
		}

		internal static bool ErrorOnce(string key, string message)
		{
			if (!MarkOnce(key))
			{
				return false;
			}
			Write(LogKind.Error, message);
			return true;
		}

		internal static bool MarkOnce(string key)
		{
			lock (Gate)
			{
				return OnceKeys.Add(key);
			}
		}

		internal static void ResetOnce()
		{
			lock (Gate)
			{
				OnceKeys.Clear();
			}
		}

		private static void Write(LogKind kind, string message)
		{
			Action<LogKind, string> sink = _sink;
			try
			{
				if (sink != null)
				{
					sink(kind, message);
				}
				else
				{
					Console.WriteLine("[" + kind.ToString() + "] " + message);
				}
			}
			catch
			{
			}
		}
	}
	internal static class LogBepInEx
	{
		internal static void Init(ManualLogSource source)
		{
			Log.SetSink(delegate(LogKind kind, string message)
			{
				switch (kind)
				{
				case LogKind.Debug:
					source.LogDebug((object)message);
					break;
				case LogKind.Info:
					source.LogInfo((object)message);
					break;
				case LogKind.Warning:
					source.LogWarning((object)message);
					break;
				default:
					source.LogError((object)message);
					break;
				}
			});
		}
	}
	internal static class ReflectionGuard
	{
		internal const BindingFlags AllMembers = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private const BindingFlags Declared = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly object Gate = new object();

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

		private static readonly Dictionary<string, int> FailureCounts = new Dictionary<string, int>(StringComparer.Ordinal);

		private static readonly Dictionary<string, Type?> TypeCache = new Dictionary<string, Type>(StringComparer.Ordinal);

		internal static int MaxFailuresBeforeDisable { get; set; } = 25;

		internal static IReadOnlyDictionary<string, string> DisabledFeatures
		{
			get
			{
				lock (Gate)
				{
					return new Dictionary<string, string>(DisabledReasons, StringComparer.Ordinal);
				}
			}
		}

		internal static event Action<string, string>? FeatureDisabled;

		internal static bool IsEnabled(string feature)
		{
			lock (Gate)
			{
				return !DisabledReasons.ContainsKey(feature);
			}
		}

		internal static void Disable(string feature, string reason)
		{
			lock (Gate)
			{
				if (DisabledReasons.ContainsKey(feature))
				{
					return;
				}
				DisabledReasons[feature] = reason;
			}
			Log.Warn("[" + feature + "] disabled: " + reason);
			try
			{
				ReflectionGuard.FeatureDisabled?.Invoke(feature, reason);
			}
			catch
			{
			}
		}

		internal static void Reset()
		{
			lock (Gate)
			{
				DisabledReasons.Clear();
				FailureCounts.Clear();
				TypeCache.Clear();
			}
		}

		internal static Type? FindType(string fullName, string feature, string? assemblyName = null)
		{
			string key = (assemblyName ?? "*") + "|" + fullName;
			lock (Gate)
			{
				if (TypeCache.TryGetValue(key, out Type value) && value != null)
				{
					return value;
				}
			}
			Type type = null;
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assemblyName == null || string.Equals(assembly.GetName().Name, assemblyName, StringComparison.Ordinal))
					{
						type = assembly.GetType(fullName, throwOnError: false);
						if (type != null)
						{
							break;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Disable(feature, "type lookup " + fullName + " threw " + ex.GetType().Name + ": " + ex.Message);
				return null;
			}
			if (type != null)
			{
				lock (Gate)
				{
					TypeCache[key] = type;
				}
			}
			else
			{
				Disable(feature, "type " + fullName + ((assemblyName != null) ? (" (in " + assemblyName + ")") : "") + " not found");
			}
			return type;
		}

		internal static FieldInfo? Field(Type? type, string name, string feature)
		{
			if (type == null)
			{
				Disable(feature, "field " + name + ": owner type is null");
				return null;
			}
			Type type2 = type;
			while (type2 != null)
			{
				FieldInfo field = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
				type2 = type2.BaseType;
			}
			Disable(feature, "field " + type.FullName + "." + name + " not found");
			return null;
		}

		internal static MethodInfo? Method(Type? type, string name, Type[]? parameterTypes, string feature)
		{
			if (type == null)
			{
				Disable(feature, "method " + name + ": owner type is null");
				return null;
			}
			Type type2 = type;
			while (type2 != null)
			{
				List<MethodInfo> list = (from m in type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
					where m.Name == name
					select m).ToList();
				if (list.Count != 0)
				{
					if (parameterTypes == null)
					{
						if (list.Count == 1)
						{
							return list[0];
						}
						Disable(feature, "method " + type2.FullName + "." + name + " is ambiguous (" + list.Count + " overloads); pass parameter types");
						return null;
					}
					foreach (MethodInfo item in list)
					{
						if (ParametersMatch(item.GetParameters(), parameterTypes))
						{
							return item;
						}
					}
				}
				type2 = type2.BaseType;
			}
			Disable(feature, "method " + type.FullName + "." + name + Signature(parameterTypes) + " not found");
			return null;
		}

		internal static PropertyInfo? Property(Type? type, string name, string feature)
		{
			if (type == null)
			{
				Disable(feature, "property " + name + ": owner type is null");
				return null;
			}
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					return property;
				}
				type2 = type2.BaseType;
			}
			Disable(feature, "property " + type.FullName + "." + name + " not found");
			return null;
		}

		internal static bool TryGet<T>(FieldInfo? field, object? instance, out T value, string feature)
		{
			value = default(T);
			if (field == null || !IsEnabled(feature))
			{
				return false;
			}
			try
			{
				object value2 = field.GetValue(field.IsStatic ? null : instance);
				if (value2 is T val)
				{
					value = val;
					return true;
				}
				if (value2 == null && default(T) == null)
				{
					return true;
				}
				Log.WarnOnce(feature + "|type|" + field.Name, "[" + feature + "] field " + field.Name + " is " + (value2?.GetType().FullName ?? "null") + ", expected " + typeof(T).FullName);
				return false;
			}
			catch (Exception e)
			{
				CountFailure(feature, "get " + field.Name, e);
				return false;
			}
		}

		internal static bool TryGet<T>(PropertyInfo? property, object? instance, out T value, string feature)
		{
			value = default(T);
			MethodInfo methodInfo = property?.GetGetMethod(nonPublic: true);
			if (property == null || methodInfo == null || !IsEnabled(feature))
			{
				return false;
			}
			try
			{
				object value2 = property.GetValue(methodInfo.IsStatic ? null : instance, null);
				if (value2 is T val)
				{
					value = val;
					return true;
				}
				if (value2 == null && default(T) == null)
				{
					return true;
				}
				Log.WarnOnce(feature + "|type|" + property.Name, "[" + feature + "] property " + property.Name + " is " + (value2?.GetType().FullName ?? "null") + ", expected " + typeof(T).FullName);
				return false;
			}
			catch (Exception e)
			{
				CountFailure(feature, "get " + property.Name, e);
				return false;
			}
		}

		internal static bool TrySet(FieldInfo? field, object? instance, object? value, string feature)
		{
			if (field == null || !IsEnabled(feature))
			{
				return false;
			}
			try
			{
				field.SetValue(field.IsStatic ? null : instance, value);
				return true;
			}
			catch (Exception e)
			{
				CountFailure(feature, "set " + field.Name, e);
				return false;
			}
		}

		internal static bool TryInvoke(MethodInfo? method, object? instance, object?[]? args, out object? result, string feature)
		{
			result = null;
			if (method == null || !IsEnabled(feature))
			{
				return false;
			}
			try
			{
				result = method.Invoke(method.IsStatic ? null : instance, args);
				return true;
			}
			catch (TargetInvocationException ex) when (ex.InnerException != null)
			{
				CountFailure(feature, "invoke " + method.Name, ex.InnerException);
				return false;
			}
			catch (Exception e)
			{
				CountFailure(feature, "invoke " + method.Name, e);
				return false;
			}
		}

		internal static void Run(string key, Action body)
		{
			if (!IsEnabled(key))
			{
				return;
			}
			try
			{
				body();
			}
			catch (Exception e)
			{
				CountFailure(key, "threw", e);
			}
		}

		internal static T Run<T>(string key, Func<T> body, T fallback)
		{
			if (!IsEnabled(key))
			{
				return fallback;
			}
			try
			{
				return body();
			}
			catch (Exception e)
			{
				CountFailure(key, "threw", e);
				return fallback;
			}
		}

		internal static bool Prefix(string key, Func<bool> body)
		{
			return Run(key, body, fallback: true);
		}

		internal static int FailureCount(string key)
		{
			lock (Gate)
			{
				int value;
				return FailureCounts.TryGetValue(key, out value) ? value : 0;
			}
		}

		private static void CountFailure(string key, string what, Exception e)
		{
			int value;
			lock (Gate)
			{
				FailureCounts.TryGetValue(key, out value);
				value++;
				FailureCounts[key] = value;
			}
			if (value == 1)
			{
				Log.Error("[" + key + "] " + what + ": " + e);
			}
			if (value >= MaxFailuresBeforeDisable)
			{
				Disable(key, value + " exceptions (first logged above)");
			}
		}

		private static bool ParametersMatch(ParameterInfo[] actual, Type[] expected)
		{
			if (actual.Length != expected.Length)
			{
				return false;
			}
			for (int i = 0; i < actual.Length; i++)
			{
				if (actual[i].ParameterType != expected[i])
				{
					return false;
				}
			}
			return true;
		}

		private static string Signature(Type[]? parameterTypes)
		{
			if (parameterTypes != null)
			{
				return "(" + string.Join(", ", parameterTypes.Select((Type t) => t.Name)) + ")";
			}
			return "";
		}
	}
	internal static class TexGen
	{
		private delegate float CoverageFn(float x, float y);

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

		internal static Sprite RoundedRect(int radius = 12, int size = 0)
		{
			if (size <= 0)
			{
				size = radius * 2 + 4;
			}
			string key = "rr|" + radius + "|" + size;
			return Get(key, delegate
			{
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				Texture2D obj = NewTexture(size, size, key);
				Paint(obj, (float x, float y) => TexGenMath.FillCoverage(TexGenMath.RoundedRectDistance(x, y, size, size, radius)));
				return Sprite.Create(obj, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)(radius + 1), (float)(radius + 1), (float)(radius + 1), (float)(radius + 1)));
			});
		}

		internal static Sprite Outline(int radius = 12, int thickness = 2, int size = 0)
		{
			if (size <= 0)
			{
				size = radius * 2 + 4;
			}
			string key = "ol|" + radius + "|" + thickness + "|" + size;
			return Get(key, delegate
			{
				//IL_0068: 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)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				Texture2D obj = NewTexture(size, size, key);
				Paint(obj, (float x, float y) => TexGenMath.StrokeCoverage(TexGenMath.RoundedRectDistance(x, y, size, size, radius), thickness));
				int num = Mathf.Max(radius, thickness) + 1;
				return Sprite.Create(obj, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)num, (float)num, (float)num, (float)num));
			});
		}

		internal static Sprite Circle(int diameter = 64, int thickness = 0)
		{
			string key = "ci|" + diameter + "|" + thickness;
			return Get(key, delegate
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				Texture2D obj = NewTexture(diameter, diameter, key);
				float r = (float)diameter * 0.5f;
				Paint(obj, delegate(float x, float y)
				{
					float distance = TexGenMath.CircleDistance(x, y, r, r, r - 0.5f);
					return (thickness <= 0) ? TexGenMath.FillCoverage(distance) : TexGenMath.StrokeCoverage(distance, thickness);
				});
				return Sprite.Create(obj, new Rect(0f, 0f, (float)diameter, (float)diameter), new Vector2(0.5f, 0.5f), 100f);
			});
		}

		internal static Sprite White()
		{
			return Get("white", delegate
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				Texture2D obj = NewTexture(1, 1, "white");
				obj.SetPixel(0, 0, Color.white);
				obj.Apply(false, false);
				return Sprite.Create(obj, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 100f);
			});
		}

		private static Sprite Get(string key, Func<Sprite> create)
		{
			if (Cache.TryGetValue(key, out Sprite value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = create();
			((Object)value).name = "LcTexGen_" + key;
			((Object)value).hideFlags = (HideFlags)52;
			Cache[key] = value;
			return value;
		}

		private static Texture2D NewTexture(int w, int h, string key)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0031: Expected O, but got Unknown
			return new Texture2D(w, h, (TextureFormat)4, false)
			{
				name = "LcTexGen_" + key,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1,
				hideFlags = (HideFlags)52
			};
		}

		private static void Paint(Texture2D tex, CoverageFn coverage)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			int width = ((Texture)tex).width;
			int height = ((Texture)tex).height;
			Color32[] array = (Color32[])(object)new Color32[width * height];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					float num = coverage((float)j + 0.5f, (float)i + 0.5f);
					array[i * width + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num * 255f));
				}
			}
			tex.SetPixels32(array);
			tex.Apply(false, false);
		}
	}
	internal static class TexGenMath
	{
		internal static float RoundedRectDistance(float px, float py, float w, float h, float r)
		{
			r = Math.Max(0f, Math.Min(r, Math.Min(w, h) * 0.5f));
			float num = w * 0.5f;
			float num2 = h * 0.5f;
			float val = Math.Abs(px - num) - (num - r);
			float num3 = Math.Abs(py - num2) - (num2 - r);
			float num4 = Math.Max(val, 0f);
			float num5 = Math.Max(num3, 0f);
			float num6 = (float)Math.Sqrt(num4 * num4 + num5 * num5);
			float num7 = Math.Min(Math.Max(val, num3), 0f);
			return num6 + num7 - r;
		}

		internal static float CircleDistance(float px, float py, float cx, float cy, float r)
		{
			float num = px - cx;
			float num2 = py - cy;
			return (float)Math.Sqrt(num * num + num2 * num2) - r;
		}

		internal static float FillCoverage(float distance)
		{
			return Clamp01(0.5f - distance);
		}

		internal static float StrokeCoverage(float distance, float thickness)
		{
			float num = FillCoverage(distance);
			float num2 = FillCoverage(distance + thickness);
			return Clamp01(num - num2);
		}

		internal static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}
	}
	internal static class UiFactory
	{
		internal static class Theme
		{
			internal static Color PanelBg = new Color(0.05f, 0.05f, 0.06f, 0.92f);

			internal static Color PanelBorder = new Color(1f, 0.45f, 0.1f, 0.9f);

			internal static Color Text = new Color(0.98f, 0.62f, 0.25f, 1f);

			internal static Color TextDim = new Color(0.75f, 0.6f, 0.45f, 1f);

			internal static Color ButtonBg = new Color(0.16f, 0.09f, 0.05f, 0.95f);

			internal static Color ButtonHighlight = new Color(0.45f, 0.22f, 0.07f, 1f);

			internal static Color ButtonPressed = new Color(0.7f, 0.33f, 0.08f, 1f);

			internal static Color ButtonDisabled = new Color(0.12f, 0.12f, 0.12f, 0.7f);

			internal static Color Danger = new Color(0.9f, 0.18f, 0.15f, 1f);

			internal static Color BackdropColor = new Color(0f, 0f, 0f, 0.72f);

			internal static int CornerRadius = 10;

			internal static float FontSize = 26f;
		}

		internal static readonly Vector2 ReferenceResolution = new Vector2(1920f, 1080f);

		internal static Canvas Canvas(string name, int sortingOrder, bool dontDestroyOnLoad = false)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.layer = 5;
			if (dontDestroyOnLoad)
			{
				Object.DontDestroyOnLoad((Object)(object)val);
			}
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = sortingOrder;
			obj.pixelPerfect = false;
			CanvasScaler obj2 = val.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = ReferenceResolution;
			obj2.screenMatchMode = (ScreenMatchMode)0;
			obj2.matchWidthOrHeight = 0.5f;
			val.AddComponent<GraphicRaycaster>();
			return obj;
		}

		internal static RectTransform Rect(Transform parent, string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = 5
			}.transform;
			((Transform)val).SetParent(parent, false);
			return val;
		}

		internal static RectTransform Fill(RectTransform rt, float padding = 0f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.pivot = new Vector2(0.5f, 0.5f);
			rt.offsetMin = new Vector2(padding, padding);
			rt.offsetMax = new Vector2(0f - padding, 0f - padding);
			return rt;
		}

		internal static RectTransform Place(RectTransform rt, Vector2 anchor, Vector2 offset, Vector2 size, Vector2? pivot = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_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)
			rt.anchorMin = anchor;
			rt.anchorMax = anchor;
			rt.pivot = pivot ?? anchor;
			rt.anchoredPosition = offset;
			rt.sizeDelta = size;
			return rt;
		}

		internal static RectTransform PlaceTL(RectTransform rt, float cx, float cy, float w, float h)
		{
			//IL_000b: 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_0035: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = new Vector2(0f, 1f);
			rt.anchorMax = new Vector2(0f, 1f);
			rt.pivot = new Vector2(0.5f, 0.5f);
			rt.anchoredPosition = new Vector2(cx, 0f - cy);
			rt.sizeDelta = new Vector2(w, h);
			return rt;
		}

		internal static LayoutElement Size(Component c, float width = -1f, float height = -1f, float flexibleWidth = -1f)
		{
			LayoutElement val = c.GetComponent<LayoutElement>();
			if ((Object)(object)val == (Object)null)
			{
				val = c.gameObject.AddComponent<LayoutElement>();
			}
			val.preferredWidth = width;
			val.preferredHeight = height;
			val.minHeight = height;
			val.flexibleWidth = flexibleWidth;
			return val;
		}

		internal static VerticalLayoutGroup Vertical(Component c, float spacing = 8f, int padding = 12)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			VerticalLayoutGroup obj = c.gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing;
			((LayoutGroup)obj).padding = new RectOffset(padding, padding, padding, padding);
			((LayoutGroup)obj).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			return obj;
		}

		internal static HorizontalLayoutGroup Horizontal(Component c, float spacing = 8f, int padding = 0)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			HorizontalLayoutGroup obj = c.gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing;
			((LayoutGroup)obj).padding = new RectOffset(padding, padding, padding, padding);
			((LayoutGroup)obj).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			return obj;
		}

		internal static Image Panel(Transform parent, string name, Color? color = null, bool border = true)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Fill(Rect(parent, name));
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			obj.sprite = TexGen.RoundedRect(Theme.CornerRadius);
			obj.type = (Type)1;
			((Graphic)obj).color = (Color)(((??)color) ?? Theme.PanelBg);
			((Graphic)obj).raycastTarget = true;
			if (border)
			{
				Image obj2 = ((Component)Fill(Rect((Transform)(object)val, "Border"))).gameObject.AddComponent<Image>();
				obj2.sprite = TexGen.Outline(Theme.CornerRadius);
				obj2.type = (Type)1;
				((Graphic)obj2).color = Theme.PanelBorder;
				((Graphic)obj2).raycastTarget = false;
			}
			return obj;
		}

		internal static TextMeshProUGUI Text(Transform parent, string text, float size = 0f, TextAlignmentOptions align = (TextAlignmentOptions)513, Color? color = null, string name = "Text")
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = ((Component)Rect(parent, name)).gameObject.AddComponent<TextMeshProUGUI>();
			TMP_FontAsset val2 = FontProvider.Get();
			if ((Object)(object)val2 != (Object)null)
			{
				((TMP_Text)val).font = val2;
			}
			((TMP_Text)val).text = text;
			((TMP_Text)val).fontSize = ((size > 0f) ? size : Theme.FontSize);
			((TMP_Text)val).alignment = align;
			((Graphic)val).color = (Color)(((??)color) ?? Theme.Text);
			((TMP_Text)val).enableWordWrapping = true;
			((TMP_Text)val).overflowMode = (TextOverflowModes)1;
			((Graphic)val).raycastTarget = false;
			return val;
		}

		internal static Button Button(Transform parent, string label, Action onClick, Vector2? size = null, string? name = null)
		{
			//IL_0036: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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)
			RectTransform obj = Rect(parent, name ?? ("Button_" + label));
			obj.sizeDelta = (Vector2)(((??)size) ?? new Vector2(260f, 52f));
			Image val = ((Component)obj).gameObject.AddComponent<Image>();
			val.sprite = TexGen.RoundedRect(Theme.CornerRadius);
			val.type = (Type)1;
			((Graphic)val).color = Color.white;
			Button val2 = ((Component)obj).gameObject.AddComponent<Button>();
			((Selectable)val2).targetGraphic = (Graphic)(object)val;
			((Selectable)val2).colors = Colors();
			((UnityEvent)val2.onClick).AddListener(Guarded("Button " + label, onClick));
			Fill(((TMP_Text)Text((Transform)(object)obj, label, 0f, (TextAlignmentOptions)514, null, "Label")).rectTransform, 6f);
			if (size.HasValue)
			{
				Size((Component)(object)val2, size.Value.x, size.Value.y);
			}
			return val2;
		}

		internal static Button CycleButton(Transform parent, Func<string> label, Action onClick, Vector2? size = null, string? name = null)
		{
			TextMeshProUGUI text = null;
			Button val = Button(parent, label(), delegate
			{
				onClick();
				if ((Object)(object)text != (Object)null)
				{
					((TMP_Text)text).text = label();
				}
			}, size, name);
			text = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(true);
			return val;
		}

		internal static void SetLabel(Button button, string label)
		{
			TextMeshProUGUI componentInChildren = ((Component)button).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = label;
			}
		}

		internal static Image Picture(Transform parent, string name, Sprite? sprite, Color color, bool raycast = false)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)Rect(parent, name)).gameObject.AddComponent<Image>();
			obj.sprite = (Sprite)(((Object)(object)sprite != (Object)null) ? ((object)sprite) : ((object)TexGen.White()));
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = raycast;
			obj.preserveAspect = (Object)(object)sprite != (Object)null;
			return obj;
		}

		internal static Image Line(RectTransform parent, Vector2 from, Vector2 to, float thickness, Color color)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			Image obj = Picture((Transform)(object)parent, "Line", null, color);
			UiMath.Line(from.x, from.y, to.x, to.y, out var centreX, out var centreY, out var length, out var angleDeg);
			PlaceTL(((Graphic)obj).rectTransform, centreX, centreY, length, thickness);
			((Transform)((Graphic)obj).rectTransform).localRotation = Quaternion.Euler(0f, 0f, angleDeg);
			return obj;
		}

		internal static RectTransform Backdrop(Transform parent, string name = "Backdrop", Color? color = null)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = Fill(Rect(parent, name));
			Image obj2 = ((Component)obj).gameObject.AddComponent<Image>();
			obj2.sprite = TexGen.White();
			((Graphic)obj2).color = (Color)(((??)color) ?? Theme.BackdropColor);
			((Graphic)obj2).raycastTarget = true;
			return obj;
		}

		internal static Toggle Toggle(Transform parent, string label, bool value, Action<bool> onChanged, float height = 44f)
		{
			//IL_0019: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = Rect(parent, "Toggle_" + label);
			obj.sizeDelta = new Vector2(400f, height);
			Size((Component)(object)obj, -1f, height, 1f);
			Image val = ((Component)obj).gameObject.AddComponent<Image>();
			val.sprite = TexGen.RoundedRect(Theme.CornerRadius);
			val.type = (Type)1;
			((Graphic)val).color = Color.white;
			RectTransform obj2 = Place(Rect((Transform)(object)obj, "Box"), new Vector2(0f, 0.5f), new Vector2(8f, 0f), new Vector2(height - 12f, height - 12f));
			Image obj3 = ((Component)obj2).gameObject.AddComponent<Image>();
			obj3.sprite = TexGen.Outline(6);
			obj3.type = (Type)1;
			((Graphic)obj3).color = Theme.Text;
			((Graphic)obj3).raycastTarget = false;
			Image val2 = ((Component)Fill(Rect((Transform)(object)obj2, "Check"), 6f)).gameObject.AddComponent<Image>();
			val2.sprite = TexGen.RoundedRect(4);
			val2.type = (Type)1;
			((Graphic)val2).color = Theme.Text;
			((Graphic)val2).raycastTarget = false;
			TextMeshProUGUI obj4 = Text((Transform)(object)obj, label, 0f, (TextAlignmentOptions)513, null, "Label");
			((TMP_Text)obj4).rectTransform.anchorMin = new Vector2(0f, 0f);
			((TMP_Text)obj4).rectTransform.anchorMax = new Vector2(1f, 1f);
			((TMP_Text)obj4).rectTransform.offsetMin = new Vector2(height + 4f, 0f);
			((TMP_Text)obj4).rectTransform.offsetMax = new Vector2(-8f, 0f);
			Toggle obj5 = ((Component)obj).gameObject.AddComponent<Toggle>();
			((Selectable)obj5).targetGraphic = (Graphic)(object)val;
			obj5.graphic = (Graphic)(object)val2;
			((Selectable)obj5).colors = Colors(transparentNormal: true);
			obj5.isOn = value;
			UnityAction<bool> val3 = Guarded("Toggle " + label, onChanged);
			((UnityEvent<bool>)(object)obj5.onValueChanged).AddListener(val3);
			return obj5;
		}

		internal static ScrollRect ScrollList(Transform parent, string name, out RectTransform content, float spacing = 6f)
		{
			//IL_007d: 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_00b6: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = Fill(Rect(parent, name));
			ScrollRect val = ((Component)obj).gameObject.AddComponent<ScrollRect>();
			val.horizontal = false;
			val.vertical = true;
			val.movementType = (MovementType)2;
			val.scrollSensitivity = 30f;
			RectTransform val2 = Fill(Rect((Transform)(object)obj, "Viewport"));
			((Component)val2).gameObject.AddComponent<RectMask2D>();
			((Graphic)((Component)val2).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0f);
			content = Rect((Transform)(object)val2, "Content");
			content.anchorMin = new Vector2(0f, 1f);
			content.anchorMax = new Vector2(1f, 1f);
			content.pivot = new Vector2(0.5f, 1f);
			content.anchoredPosition = Vector2.zero;
			content.sizeDelta = Vector2.zero;
			((LayoutGroup)Vertical((Component)(object)content, spacing, 4)).childAlignment = (TextAnchor)1;
			ContentSizeFitter obj2 = ((Component)content).gameObject.AddComponent<ContentSizeFitter>();
			obj2.verticalFit = (FitMode)2;
			obj2.horizontalFit = (FitMode)0;
			val.viewport = val2;
			val.content = content;
			return val;
		}

		internal static void ScrollIntoView(ScrollRect scroll, RectTransform item)
		{
			ReflectionGuard.Run("UiFactory.ScrollIntoView", delegate
			{
				//IL_002a: 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_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Unknown result type (might be due to invalid IL or missing references)
				RectTransform content = scroll.content;
				RectTransform val = (RectTransform)(((Object)(object)scroll.viewport != (Object)null) ? ((object)scroll.viewport) : ((object)(RectTransform)((Component)scroll).transform));
				if (!((Object)(object)content == (Object)null))
				{
					Canvas.ForceUpdateCanvases();
					Rect rect = content.rect;
					float height = ((Rect)(ref rect)).height;
					rect = val.rect;
					float height2 = ((Rect)(ref rect)).height;
					if (!(height <= height2))
					{
						float y = ((Transform)content).InverseTransformPoint(((Transform)item).position).y;
						rect = item.rect;
						float num = 0f - (y + ((Rect)(ref rect)).height * (1f - item.pivot.y));
						rect = item.rect;
						float num2 = num + ((Rect)(ref rect)).height;
						float num3 = content.anchoredPosition.y;
						if (num < num3)
						{
							num3 = num;
						}
						else if (num2 > num3 + height2)
						{
							num3 = num2 - height2;
						}
						num3 = Mathf.Clamp(num3, 0f, height - height2);
						content.anchoredPosition = new Vector2(content.anchoredPosition.x, num3);
					}
				}
			});
		}

		internal static void LinkVertical(IList<Selectable> items, bool wrap = true, Selectable? left = null, Selectable? right = null)
		{
			Link(items, wrap, vertical: true, left, right);
		}

		internal static void LinkHorizontal(IList<Selectable> items, bool wrap = false, Selectable? up = null, Selectable? down = null)
		{
			Link(items, wrap, vertical: false, up, down);
		}

		internal static void Select(Selectable? target)
		{
			ReflectionGuard.Run("UiFactory.Select", delegate
			{
				EventSystem current = EventSystem.current;
				if (!((Object)(object)current == (Object)null) && !((Object)(object)target == (Object)null) && ((Component)target).gameObject.activeInHierarchy)
				{
					current.SetSelectedGameObject((GameObject)null);
					current.SetSelectedGameObject(((Component)target).gameObject);
				}
			});
		}

		internal static void Destroy(Component? root)
		{
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root.gameObject);
			}
		}

		private static void Link(IList<Selectable> items, bool wrap, bool vertical, Selectable? sideA, Selectable? sideB)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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)
			List<Selectable> list = new List<Selectable>();
			foreach (Selectable item in items)
			{
				if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy && item.IsInteractable())
				{
					list.Add(item);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				Selectable val = ((i > 0) ? list[i - 1] : ((wrap && list.Count > 1) ? list[list.Count - 1] : null));
				Selectable val2 = ((i < list.Count - 1) ? list[i + 1] : ((wrap && list.Count > 1) ? list[0] : null));
				Navigation val3 = default(Navigation);
				((Navigation)(ref val3)).mode = (Mode)4;
				Navigation navigation = val3;
				if (vertical)
				{
					((Navigation)(ref navigation)).selectOnUp = val;
					((Navigation)(ref navigation)).selectOnDown = val2;
					((Navigation)(ref navigation)).selectOnLeft = sideA;
					((Navigation)(ref navigation)).selectOnRight = sideB;
				}
				else
				{
					((Navigation)(ref navigation)).selectOnLeft = val;
					((Navigation)(ref navigation)).selectOnRight = val2;
					((Navigation)(ref navigation)).selectOnUp = sideA;
					((Navigation)(ref navigation)).selectOnDown = sideB;
				}
				list[i].navigation = navigation;
			}
		}

		private static ColorBlock Colors(bool transparentNormal = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock;
			((ColorBlock)(ref defaultColorBlock)).normalColor = (Color)(transparentNormal ? new Color(0f, 0f, 0f, 0f) : Theme.ButtonBg);
			((ColorBlock)(ref defaultColorBlock)).highlightedColor = Theme.ButtonHighlight;
			((ColorBlock)(ref defaultColorBlock)).selectedColor = Theme.ButtonHighlight;
			((ColorBlock)(ref defaultColorBlock)).pressedColor = Theme.ButtonPressed;
			((ColorBlock)(ref defaultColorBlock)).disabledColor = Theme.ButtonDisabled;
			((ColorBlock)(ref defaultColorBlock)).colorMultiplier = 1f;
			((ColorBlock)(ref defaultColorBlock)).fadeDuration = 0.08f;
			return defaultColorBlock;
		}

		private static UnityAction Guarded(string key, Action action)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return (UnityAction)delegate
			{
				ReflectionGuard.Run(key, action);
			};
		}

		private static UnityAction<T> Guarded<T>(string key, Action<T> action)
		{
			return delegate(T v)
			{
				ReflectionGuard.Run(key, delegate
				{
					action(v);
				});
			};
		}
	}
	internal static class UiMath
	{
		internal static void Line(float fromX, float fromY, float toX, float toY, out float centreX, out float centreY, out float length, out float angleDeg)
		{
			float num = toX - fromX;
			float num2 = 0f - (toY - fromY);
			centreX = (fromX + toX) * 0.5f;
			centreY = (fromY + toY) * 0.5f;
			length = (float)Math.Sqrt(num * num + num2 * num2);
			angleDeg = ((length > 0f) ? ((float)(Math.Atan2(num2, num) * (180.0 / Math.PI))) : 0f);
		}
	}
}
namespace Lifeline
{
	internal static class Hud
	{
		private static Canvas? _canvas;

		private static RectTransform? _root;

		private static TextMeshProUGUI? _text;

		private static Image? _fill;

		private static RectTransform? _bar;

		private static string? _toast;

		private static float _toastUntil;

		private static string? _shown;

		internal static void Prompt(string? text, float progress)
		{
			if (!Ensure())
			{
				return;
			}
			string text2 = ((_toast != null && Time.realtimeSinceStartup < _toastUntil) ? _toast : null);
			string text3 = text2 ?? text;
			bool flag = text3 != null;
			if (((Component)_root).gameObject.activeSelf != flag)
			{
				((Component)_root).gameObject.SetActive(flag);
			}
			if (flag)
			{
				if ((object)text3 != _shown)
				{
					_shown = text3;
					((TMP_Text)_text).text = text3;
				}
				bool flag2 = text2 == null && progress > 0f;
				if (((Component)_bar).gameObject.activeSelf != flag2)
				{
					((Component)_bar).gameObject.SetActive(flag2);
				}
				_fill.fillAmount = Mathf.Clamp01(progress);
			}
		}

		internal static void Toast(string text, float seconds)
		{
			_toast = text;
			_toastUntil = Time.realtimeSinceStartup + seconds;
			Prompt(text, 0f);
		}

		internal static void Hide()
		{
			if ((Object)(object)_root != (Object)null)
			{
				((Component)_root).gameObject.SetActive(false);
			}
		}

		private static bool Ensure()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				return true;
			}
			return ReflectionGuard.Run("Lifeline.Hud", delegate
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: 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_01ce: Unknown result type (might be due to invalid IL or missing references)
				_canvas = UiFactory.Canvas("LifelineCanvas", 55, dontDestroyOnLoad: true);
				_root = UiFactory.Place(UiFactory.Rect(((Component)_canvas).transform, "Prompt"), new Vector2(0.5f, 0.36f), Vector2.zero, new Vector2(620f, 90f));
				_text = UiFactory.Text((Transform)(object)_root, "", 26f, (TextAlignmentOptions)514, Color.white);
				UiFactory.Place(((TMP_Text)_text).rectTransform, new Vector2(0.5f, 1f), new Vector2(0f, -22f), new Vector2(620f, 44f));
				((TMP_Text)_text).richText = false;
				_bar = UiFactory.Place(UiFactory.Rect((Transform)(object)_root, "Bar"), new Vector2(0.5f, 0f), new Vector2(0f, 22f), new Vector2(320f, 14f));
				Image obj = ((Component)_bar).gameObject.AddComponent<Image>();
				obj.sprite = TexGen.White();
				((Graphic)obj).color = new Color(0f, 0f, 0f, 0.55f);
				((Graphic)obj).raycastTarget = false;
				_fill = ((Component)UiFactory.Fill(UiFactory.Rect((Transform)(object)_bar, "Fill"), 2f)).gameObject.AddComponent<Image>();
				_fill.sprite = TexGen.White();
				_fill.type = (Type)3;
				_fill.fillMethod = (FillMethod)0;
				((Graphic)_fill).color = new Color(0.45f, 0.95f, 0.5f, 1f);
				((Graphic)_fill).raycastTarget = false;
				((Component)_root).gameObject.SetActive(false);
				return true;
			}, fallback: false);
		}
	}
	internal sealed class LifelineConfig
	{
		internal ConfigEntry<float> HoldSeconds { get; }

		internal ConfigEntry<float> MaxDistance { get; }

		internal ConfigEntry<int> Health { get; }

		internal ConfigEntry<int> HealthLoss { get; }

		internal ConfigEntry<int> MinHealth { get; }

		internal ConfigEntry<ReviveMode> Mode { get; }

		internal ConfigEntry<int> RevivesPerPlayer { get; }

		internal ConfigEntry<int> TeamMin { get; }

		internal ConfigEntry<float> TeamPerPlayer { get; }

		internal ConfigEntry<int> TimeLimit { get; }

		internal ConfigEntry<bool> AllowTombs { get; }

		internal ConfigEntry<Key> FallbackKey { get; }

		internal ConfigEntry<bool> DefibEnabled { get; }

		internal ConfigEntry<int> DefibPrice { get; }

		internal ConfigEntry<bool> DebugLog { get; }

		internal LifelineConfig(ConfigFile file)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Expected O, but got Unknown
			HoldSeconds = file.Bind<float>("Revive", "HoldSeconds", 5f, new ConfigDescription("Host: how long the key must be held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()));
			MaxDistance = file.Bind<float>("Revive", "MaxDistance", 3f, new ConfigDescription("Host: how close you must be to the body or tombstone (m).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			Health = file.Bind<int>("Revive", "Health", 35, new ConfigDescription("Host: health after a revive.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			HealthLoss = file.Bind<int>("Revive", "HealthLossPerRevive", 5, new ConfigDescription("Host: each further revive of the same player this round gives this much less health.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			MinHealth = file.Bind<int>("Revive", "MinHealth", 10, new ConfigDescription("Host: never less health than this.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			Mode = file.Bind<ReviveMode>("Rules", "Mode", ReviveMode.PerPlayer, "Host: PerPlayer = each player can be revived RevivesPerPlayer times per round; PerTeam = the crew shares a pool; Unlimited.");
			RevivesPerPlayer = file.Bind<int>("Rules", "RevivesPerPlayer", 2, new ConfigDescription("Host (PerPlayer).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 99), Array.Empty<object>()));
			TeamMin = file.Bind<int>("Rules", "TeamRevivesMin", 4, new ConfigDescription("Host (PerTeam): at least this many revives per round...", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 99), Array.Empty<object>()));
			TeamPerPlayer = file.Bind<float>("Rules", "TeamRevivesPerPlayer", 1.25f, new ConfigDescription("Host (PerTeam): ...or players x this, if more.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			TimeLimit = file.Bind<int>("Rules", "TimeLimitSeconds", 120, new ConfigDescription("Host: seconds after death until a player can no longer be revived (0 = no limit).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3600), Array.Empty<object>()));
			AllowTombs = file.Bind<bool>("Rules", "AllowTombs", true, "Host: when the body is gone, revive at a tombstone where the player died.");
			DefibEnabled = file.Bind<bool>("Defibrillator", "Enabled", true, "Host: charges can be bought in the terminal (\"defib buy\"); each revives once beyond the revive limit.");
			DefibPrice = file.Bind<int>("Defibrillator", "Price", 150, new ConfigDescription("Host: credits per charge.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>()));
			FallbackKey = file.Bind<Key>("Input", "KeyWithoutInputUtils", (Key)32, "The revive key when InputUtils is not installed (with InputUtils: rebind it in its keybind menu).");
			DebugLog = file.Bind<bool>("Debug", "VerboseLogging", false, "Log every revive request and acknowledgement.");
		}

		internal ReviveRules BuildRules()
		{
			ReviveRules reviveRules = new ReviveRules();
			reviveRules.HoldSeconds = HoldSeconds.Value;
			reviveRules.MaxDistance = MaxDistance.Value;
			reviveRules.Health = Health.Value;
			reviveRules.HealthLossPerRevive = HealthLoss.Value;
			reviveRules.MinHealth = MinHealth.Value;
			reviveRules.Mode = Mode.Value;
			reviveRules.RevivesPerPlayer = RevivesPerPlayer.Value;
			reviveRules.TeamRevivesMin = TeamMin.Value;
			reviveRules.TeamRevivesPerPlayer = TeamPerPlayer.Value;
			reviveRules.TimeLimitSeconds = TimeLimit.Value;
			reviveRules.AllowTombs = AllowTombs.Value;
			reviveRules.DefibEnabled = DefibEnabled.Value;
			reviveRules.DefibPrice = DefibPrice.Value;
			reviveRules.Validate();
			return reviveRules;
		}
	}
	internal static class Net
	{
		internal const string Identifier = "lifeline.net";

		private const int MaxQueue = 512;

		private static LNetworkMessage<string>? _msg;

		internal static readonly Queue<KeyValuePair<ulong, byte[]>> ServerInbox = new Queue<KeyValuePair<ulong, byte[]>>();

		internal static readonly Queue<byte[]> ClientInbox = new Queue<byte[]>();

		internal static bool Ready => _msg != null;

		internal static void Init()
		{
			if (_msg != null)
			{
				return;
			}
			try
			{
				_msg = Connect();
				_msg.OnServerReceived += delegate(string text, ulong sender)
				{
					Enqueue(text, delegate(byte[] d)
					{
						ServerInbox.Enqueue(new KeyValuePair<ulong, byte[]>(sender, d));
					}, ServerInbox.Count);
				};
				_msg.OnClientReceived += delegate(string text)
				{
					Enqueue(text, delegate(byte[] d)
					{
						ClientInbox.Enqueue(d);
					}, ClientInbox.Count);
				};
				Log.Info("Lifeline: LethalNetworkAPI message registered (lifeline.net)");
			}
			catch (Exception ex)
			{
				_msg = null;
				Log.Error("Lifeline: LethalNetworkAPI registration failed, revives are off: " + ex);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static LNetworkMessage<string> Connect()
		{
			return LNetworkMessage<string>.Connect("lifeline.net", (Action<string, ulong>)null, (Action<string>)null, (Action<string, ulong>)null);
		}

		private static void Enqueue(string text, Action<byte[]> add, int count)
		{
			try
			{
				if (count < 512 && WireText.TryDecode(text, out byte[] packet))
				{
					add(packet);
				}
			}
			catch (Exception ex)
			{
				Log.ErrorOnce("Lifeline.Net.Receive", "Lifeline: receive failed: " + ex);
			}
		}

		internal static bool IsConnected()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.IsListening && singleton.IsConnectedClient)
			{
				return !singleton.ShutdownInProgress;
			}
			return false;
		}

		internal static bool IsHost()
		{
			if ((Object)(object)NetworkManager.Singleton != (Object)null)
			{
				return NetworkManager.Singleton.IsServer;
			}
			return false;
		}

		internal static ulong[] AllClients()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				return Array.Empty<ulong>();
			}
			return new List<ulong>(singleton.ConnectedClientsIds).ToArray();
		}

		internal static void ToServer(Msg m)
		{
			if (_msg == null || !IsConnected())
			{
				return;
			}
			try
			{
				_msg.SendServer(WireText.Encode(Wire.Encode(m)));
			}
			catch (Exception ex)
			{
				Log.WarnOnce("Lifeline.Net.SendServer", "Lifeline: send to host failed: " + ex.Message);
			}
		}

		internal static void ToClients(byte[] packet, ulong[] targets)
		{
			if (_msg == null || targets.Length == 0 || !IsConnected() || !IsHost())
			{
				return;
			}
			try
			{
				_msg.SendClients(WireText.Encode(packet), targets);
			}
			catch (Exception ex)
			{
				Log.WarnOnce("Lifeline.Net.SendClients", "Lifeline: send to clients failed: " + ex.Message);
			}
		}
	}
	[BepInPlugin("dev.thatumi.Lifeline", "Lifeline", "0.2.0")]
	[BepInDependency("LethalNetworkAPI", "3.4.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private const string LnapiGuid = "LethalNetworkAPI";

		private static readonly string[] OtherReviveMods = new string[4] { "UltimateRevive", "ReviveCompany", "BetterRevive", "RevivePlayers" };

		private void Awake()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			LogBepInEx.Init(((BaseUnityPlugin)this).Logger);
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				string[] otherReviveMods = OtherReviveMods;
				int num = 0;
				while (num < otherReviveMods.Length)
				{
					string value = otherReviveMods[num];
					if (pluginInfo.Key.IndexOf(value, StringComparison.OrdinalIgnoreCase) < 0)
					{
						BepInPlugin metadata = pluginInfo.Value.Metadata;
						if ((((metadata != null) ? metadata.Name : null) ?? "").IndexOf(value, StringComparison.OrdinalIgnoreCase) < 0)
						{
							num++;
							continue;
						}
					}
					Log.Error("Lifeline: another revive mod is installed (" + pluginInfo.Key + "). Two revive mods on the same bodies desync revives, so Lifeline is OFF. Remove one of them.");
					return;
				}
			}
			LifelineConfig cfg;
			try
			{
				cfg = new LifelineConfig(((BaseUnityPlugin)this).Config);
			}
			catch (Exception ex)
			{
				Log.Error("Lifeline config failed, plugin disabled: " + ex);
				return;
			}
			try
			{
				ReviveInput.Init(cfg);
			}
			catch (Exception ex2)
			{
				Log.Error("Lifeline input setup failed (no revive key): " + ex2);
			}
			Net.Init();
			Session.Init(cfg);
			try
			{
				Harmony val = new Harmony("dev.thatumi.Lifeline");
				val.PatchAll(typeof(GamePatches));
				val.PatchAll(typeof(TerminalPatches));
			}
			catch (Exception ex3)
			{
				Log.Error("Lifeline: patching failed, revives are off: " + ex3);
				return;
			}
			Runner.Ensure();
			Log.Info("Lifeline 0.2.0 loaded");
		}
	}
	internal sealed class Runner : MonoBehaviour
	{
		private static Runner? _instance;

		private static readonly Action TickAction = Session.Tick;

		internal static void Ensure()
		{
			//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)
			//IL_001e: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("LifelineRunner");
				Object.DontDestroyOnLoad((Object)val);
				((Object)val).hideFlags = (HideFlags)61;
				_instance = val.AddComponent<Runner>();
			}
		}

		private void Update()
		{
			if (ReflectionGuard.IsEnabled("Lifeline.Tick"))
			{
				ReflectionGuard.Run("Lifeline.Tick", TickAction);
			}
		}
	}
	internal static class ReviveApplier
	{
		private static FieldInfo? _boxes;

		private static FieldInfo? _boxesAdded;

		private static FieldInfo? _yOffset;

		private static bool _looked;

		internal static bool Apply(ReviveOrder o)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound sor = StartOfRound.Instance;
			if ((Object)(object)sor == (Object)null || sor.allPlayerScripts == null || o.Slot >= sor.allPlayerScripts.Length)
			{
				return false;
			}
			PlayerControllerB p = sor.allPlayerScripts[o.Slot];
			if ((Object)(object)p == (Object)null)
			{
				return false;
			}
			if (!p.isPlayerDead)
			{
				return true;
			}
			Vector3 pos = new Vector3(o.Position.X, o.Position.Y, o.Position.Z);
			bool num = (Object)(object)p == (Object)(object)GameNetworkManager.Instance?.localPlayerController;
			Step("Body", delegate
			{
				RemoveBody(p, sor);
			});
			Step("Tomb", delegate
			{
				Tombs.Remove(o.Slot);
			});
			Step("State", delegate
			{
				ResetState(p, sor, o);
			});
			Step("Place", delegate
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				p.TeleportPlayer(pos, false, 0f, false, true);
				p.setPositionOfDeadPlayer = false;
				p.DisablePlayerModel(sor.allPlayerObjects[o.Slot], true, true);
			});
			Step("Counts", delegate
			{
				sor.livingPlayers = Math.Min(sor.livingPlayers + 1, sor.connectedPlayersAmount + 1);
				sor.allPlayersDead = false;
			});
			if (num)
			{
				Step("Owner", delegate
				{
					OwnerView(p, sor, o);
				});
			}
			Step("SpectateBoxes", delegate
			{
				RemoveSpectateBox(p);
			});
			Step("Voice", delegate
			{
				p.voiceMuffledByEnemy = false;
				if ((Object)(object)SoundManager.Instance != (Object)null)
				{
					SoundManager.Instance.playerVoicePitchTargets[o.Slot] = 1f;
					SoundManager.Instance.SetPlayerPitch(1f, (int)o.Slot);
				}
				sor.UpdatePlayerVoiceEffects();
			});
			Log.Info("Lifeline: " + p.playerUsername + " revived (" + o.Health + " HP, " + (o.Inside ? "inside" : (o.InShip ? "in the ship" : "outside")) + ")");
			return !p.isPlayerDead;
		}

		private static void Step(string what, Action body)
		{
			try
			{
				body();
			}
			catch (Exception ex)
			{
				Log.ErrorOnce("Lifeline.Apply." + what, "Lifeline: revive step '" + what + "' failed (the rest still runs): " + ex);
			}
		}

		private static void RemoveBody(PlayerControllerB p, StartOfRound sor)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			DeadBodyInfo deadBody = p.deadBody;
			if ((Object)(object)deadBody == (Object)null)
			{
				return;
			}
			GrabbableObject grabBodyObject = deadBody.grabBodyObject;
			if ((Object)(object)grabBodyObject != (Object)null)
			{
				if (grabBodyObject.isHeld && (Object)(object)grabBodyObject.playerHeldBy != (Object)null)
				{
					grabBodyObject.playerHeldBy.DropAllHeldItems(true, false, false, false, default(Vector3), default(Vector3), default(Vector3), default(Vector3), default(Vector3));
				}
				if (((NetworkBehaviour)sor).IsServer && (Object)(object)((NetworkBehaviour)grabBodyObject).NetworkObject != (Object)null && ((NetworkBehaviour)grabBodyObject).NetworkObject.IsSpawned)
				{
					((NetworkBehaviour)grabBodyObject).NetworkObject.Despawn(true);
				}
			}
			Object.Destroy((Object)(object)((Component)deadBody).gameObject);
			p.deadBody = null;
		}

		private static void ResetState(PlayerControllerB p, StartOfRound sor, ReviveOrder o)
		{
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			p.ResetPlayerBloodObjects(true);
			p.isClimbingLadder = false;
			p.clampLooking = false;
			p.inVehicleAnimation = false;
			p.overridePoisonValue = false;
			p.disableMoveInput = false;
			p.ResetZAndXRotation();
			((Collider)p.thisController).enabled = true;
			p.hasBeenCriticallyInjured = false;
			p.disableLookInput = false;
			p.disableInteract = false;
			((Behaviour)p.nightVisionRadar).enabled = false;
			p.isPlayerDead = false;
			p.enemyWaitingForBodyRagdoll = null;
			p.isPlayerControlled = true;
			p.isInsideFactory = o.Inside;
			p.isInElevator = o.InShip;
			p.isInHangarShipRoom = o.InShip;
			p.parentedToElevatorLastFrame = false;
			p.overrideGameOverSpectatePivot = null;
			((Behaviour)p.helmetLight).enabled = false;
			p.Crouch(false);
			p.criticallyInjured = false;
			if ((Object)(object)p.playerBodyAnimator != (Object)null)
			{
				p.playerBodyAnimator.SetBool("Limp", false);
			}
			p.bleedingHeavily = false;
			p.activatingItem = false;
			p.twoHanded = false;
			p.inShockingMinigame = false;
			p.inSpecialInteractAnimation = false;
			p.freeRotationInInteractAnimation = false;
			p.disableSyncInAnimation = false;
			p.inAnimationWithEnemy = null;
			p.holdingWalkieTalkie = false;
			p.speakingToWalkieTalkie = false;
			p.isSinking = false;
			p.isUnderwater = false;
			p.sinkingValue = 0f;
			p.statusEffectAudio.Stop();
			p.DisableJetpackControlsLocally();
			p.health = o.Health;
			p.mapRadarDotAnimator.SetBool("dead", false);
			p.externalForceAutoFade = Vector3.zero;
			p.carryWeight = 1f;
		}

		private static void OwnerView(PlayerControllerB p, StartOfRound sor, ReviveOrder o)
		{
			HUDManager instance = HUDManager.Instance;
			p.hasBegunSpectating = false;
			p.spectatedPlayerScript = null;
			p.hinderedMultiplier = 1f;
			p.isMovementHindered = 0;
			p.sourcesCausingSinking = 0;
			p.isInGameOverAnimation = 0f;
			((Renderer)p.thisPlayerModelArms).enabled = true;
			if (o.InShip)
			{
				p.reverbPreset = sor.shipReverb;
			}
			sor.SendChangedWeightEvent();
			sor.SetSpectateCameraToGameOverMode(false, p);
			sor.SwitchCamera(p.gameplayCamera);
			p.ChangeAudioListenerToObject(((Component)p.gameplayCamera).gameObject);
			if ((Object)(object)instance != (Object)null)
			{
				instance.SetCracksOnVisor(100f);
				instance.gasHelmetAnimator.SetBool("gasEmitting", false);
				instance.RemoveSpectateUI();
				instance.gameOverAnimator.SetTrigger("revive");
				instance.HideHUD(false);
				instance.SetNearDepthOfFieldEnabled(false);
				((Behaviour)instance.audioListenerLowPass).enabled = false;
				instance.cadaverFilter = 0f;
				instance.UpdateHealthUI((int)o.Health, false);
			}
		}

		private static void RemoveSpectateBox(PlayerControllerB p)
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			//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_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!_looked)
			{
				_looked = true;
				_boxes = typeof(HUDManager).GetField("spectatingPlayerBoxes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_boxesAdded = typeof(HUDManager).GetField("boxesAdded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_yOffset = typeof(HUDManager).GetField("yOffsetAmount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_boxes == null)
				{
					Log.Warn("Lifeline: HUDManager.spectatingPlayerBoxes not found; revived players may stay in the spectate list.");
				}
			}
			if (!(_boxes?.GetValue(instance) is IDictionary dictionary))
			{
				return;
			}
			Animator val = null;
			foreach (DictionaryEntry item in dictionary)
			{
				if (item.Value == p)
				{
					object key = item.Key;
					val = (Animator)((key is Animator) ? key : null);
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (((Component)val).gameObject.activeSelf && _boxesAdded != null && _yOffset != null)
			{
				int num = (int)_boxesAdded.GetValue(instance);
				float y = ((RectTransform)((Component)val).transform).anchoredPosition.y;
				List<RectTransform> list = new List<RectTransform>();
				foreach (DictionaryEntry item2 in dictionary)
				{
					object key2 = item2.Key;
					Animator val2 = (Animator)((key2 is Animator) ? key2 : null);
					if (val2 != null && (Object)(object)val2 != (Object)(object)val && ((Component)val2).gameObject.activeSelf)
					{
						list.Add((RectTransform)((Component)val2).transform);
					}
				}
				foreach (RectTransform item3 in list)
				{
					if (item3.anchoredPosition.y < y)
					{
						item3.anchoredPosition = new Vector2(item3.anchoredPosition.x, item3.anchoredPosition.y + 70f);
					}
				}
				_boxesAdded.SetValue(instance, Math.Max(0, num - 1));
				_yOffset.SetValue(instance, (float)_yOffset.GetValue(instance) + 70f);
			}
			dictionary.Remove(val);
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
	}
	internal static class ReviveInput
	{
		internal interface IHold
		{
			bool Held { get; }

			string Label { get; }
		}

		private sealed class KeyHold : IHold
		{
			private readonly LifelineConfig _cfg;

			public bool Held
			{
				get
				{
					//IL_0014: 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)
					Keyboard current = Keyboard.current;
					if (current == null || (int)_cfg.FallbackKey.Value == 0)
					{
						return false;
					}
					return ((ButtonControl)current[_cfg.FallbackKey.Value]).isPressed;
				}
			}

			public string Label => ((object)_cfg.FallbackKey.Value/*cast due to .constrained prefix*/).ToString();

			internal KeyHold(LifelineConfig cfg)
			{
				_cfg = cfg;
			}
		}

		internal const string InputUtilsGuid = "com.rune580.LethalCompanyInputUtils";

		private static IHold? _hold;

		internal static bool Held
		{
			get
			{
				if (_hold != null)
				{
					return _hold.Held;
				}
				return false;
			}
		}

		internal static string Label => _hold?.Label ?? "R";

		internal static void Init(LifelineConfig cfg)
		{
			//IL_0064: 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)
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.LethalCompanyInputUtils"))
			{
				_hold = ReflectionGuard.Run("Lifeline.Input.InputUtils", InputUtilsBridge.Create, null);
				if (_hold != null)
				{
					Log.Info("Lifeline: revive key registered with InputUtils (default R / D-pad up, hold)");
					return;
				}
			}
			_hold = new KeyHold(cfg);
			Log.Info("Lifeline: InputUtils not found, revive key from the config (" + ((object)cfg.FallbackKey.Value/*cast due to .constrained prefix*/).ToString() + ")");
		}
	}
	internal static class InputUtilsBridge
	{
		private sealed class ActionHold : ReviveInput.IHold
		{
			private readonly LifelineActions _a;

			public bool Held
			{
				get
				{
					if (_a.Revive != null)
					{
						return _a.Revive.IsPressed();
					}
					return false;
				}
			}

			public string Label
			{
				get
				{
					try
					{
						InputAction revive = _a.Revive;
						string text = ((revive != null) ? InputActionRebindingExtensions.GetBindingDisplayString(revive, 0, (DisplayStringOptions)4) : null);
						return string.IsNullOrEmpty(text) ? "R" : text;
					}
					catch (Exception)
					{
						return "R";
					}
				}
			}

			internal ActionHold(LifelineActions a)
			{
				_a = a;
			}
		}

		internal static ReviveInput.IHold Create()
		{
			return new ActionHold(new LifelineActions());
		}
	}
	internal sealed class LifelineActions : LcInputActions
	{
		[InputAction("<Keyboard>/r", Name = "Revive (hold)", GamepadPath = "<Gamepad>/dpad/up")]
		public InputAction Revive { get; set; }
	}
	internal static class Session
	{
		private const float TombBelowY = -80f;

		private static LifelineConfig _cfg = null;

		private static ReviveHost? _host;

		private static readonly ReviveClient Client = new ReviveClient();

		private static readonly HashSet<ulong> Known = new HashSet<ulong>();

		private static readonly Dictionary<int, Vector3> DeathPos = new Dictionary<int, Vector3>();

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

		private static readonly List<Send> Sends = new List<Send>();

		private static bool _active;

		private static bool _hostAnswered;

		private static float _helloAt;

		private static int _hellos;

		private static int _charges;

		private static int _target = -1;

		private static float _progress;

		private static float _cooldownUntil;

		internal static long NowMs => (long)(Time.realtimeSinceStartupAsDouble * 1000.0);

		internal static void Init(LifelineConfig cfg)
		{
			_cfg = cfg;
		}

		internal static void Tick()
		{
			if (!Net.Ready)
			{
				return;
			}
			if (!Net.IsConnected() || (Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null)
			{
				if (_active)
				{
					Stop();
				}
				return;
			}
			if (!_active)
			{
				Start();
			}
			long now = NowMs;
			if (_host != null)
			{
				int num = 0;
				while (Net.ServerInbox.Count > 0 && num++ < 128)
				{
					KeyValuePair<ulong, byte[]> item = Net.ServerInbox.Dequeue();
					ReflectionGuard.Run("Lifeline.Host", delegate
					{
						HostReceive(item.Key, item.Value, now);
					});
				}
				Sends.Clear();
				_host.Update(now, ToArray(Known), (int slot) => AliveHere(slot), Sends);
				foreach (Send send in Sends)
				{
					Net.ToClients(send.Data, send.Targets);
				}
			}
			int num2 = 0;
			while (Net.ClientInbox.Count > 0 && num2++ < 128)
			{
				byte[] data = Net.ClientInbox.Dequeue();
				ReflectionGuard.Run("Lifeline.Client", delegate
				{
					ClientReceive(data, now);
				});
			}
			if (!_hostAnswered && _hellos < 3 && Time.realtimeSinceStartup >= _helloAt)
			{
				_hellos++;
				_helloAt = Time.realtimeSinceStartup + 10f;
				Net.ToServer(new HelloMsg());
				if (_hellos == 3)
				{
					Log.Info("Lifeline: no answer from the host yet; if the host does not run Lifeline, revives are off in this lobby.");
				}
			}
			ReflectionGuard.Run("Lifeline.Tombs", UpdateTombs);
			ReflectionGuard.Run("Lifeline.Interact", Interact);
		}

		internal static void BeforeDeath(int slot)
		{
			PlayerControllerB val = PlayerAt(slot);
			if ((Object)(object)val != (Object)null)
			{
				InsideAtDeath[slot] = val.isInsideFactory;
			}
		}

		internal unsafe static void OnDeath(int slot)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = PlayerAt(slot);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)val).transform.position;
			DeathPos[slot] = position;
			Client.OnDeath(slot, NowMs);
			if (slot == _target)
			{
				ResetHold();
			}
			if (_host != null)
			{
				InsideAtDeath.TryGetValue(slot, out var value);
				_host.OnDeath(slot, new DeathRecord
				{
					AtMs = NowMs,
					Position = V(position),
					Inside = (value || position.y < -80f),
					InShip = val.isInHangarShipRoom
				});
				if (_cfg.DebugLog.Value)
				{
					string[] obj = new string[5]
					{
						"Lifeline: player ",
						slot.ToString(),
						" died at ",
						null,
						null
					};
					Vector3 val2 = position;
					obj[3] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString();
					obj[4] = (value ? " (inside)" : "");
					Log.Info(string.Concat(obj));
				}
			}
		}

		internal static void OnRoundOver()
		{
			Tombs.Clear();
			DeathPos.Clear();
			InsideAtDeath.Clear();
			Client.Reset();
			ResetHold();
			if (_host != null)
			{
				_host.SetRules(_cfg.BuildRules());
				_host.BeginRound(PlayerCount());
				Net.ToClients(Wire.Encode(new RulesMsg
				{
					Rules = _host.Rules
				}), Net.AllClients());
			}
		}

		internal static string DefibCommand(bool buy)
		{
			ReviveRules rules = Client.Rules;
			if (!_hostAnswered)
			{
				return "DEFIBRILLATOR\nThe host does not run Lifeline, so there are no revives in this lobby.";
			}
			if (!rules.DefibEnabled)
			{
				return "DEFIBRILLATOR\nDefibrillators are off in this lobby (host config).";
			}
			if (buy)
			{
				Net.ToServer(new BuyMsg());
				return "DEFIBRILLATOR\nOrdering one charge for " + rules.DefibPrice + " credits.\nThe host confirms it in a moment.";
			}
			return "DEFIBRILLATOR\nCharges: " + _charges + "\nPrice: " + rules.DefibPrice + " credits each\n\nA charge revives a crewmate once beyond the revive limit (it is used automatically).\nCharges last until they are used.\n\nType \"defib buy\" to order one.";
		}

		private static void Start()
		{
			_active = true;
			_hostAnswered = false;
			_helloAt = 0f;
			_hellos = 0;
			_charges = 0;
			Known.Clear();
			Client.Reset();
			Net.ServerInbox.Clear();
			Net.ClientInbox.Clear();
			if (Net.IsHost())
			{
				_host = new ReviveHost(_cfg.BuildRules())
				{
					Trace = delegate(string s)
					{
						Log.Warn("Lifeline: " + s);
					}
				};
				_host.BeginRound(PlayerCount());
			}
		}

		private static void Stop()
		{
			_active = false;
			_host = null;
			Tombs.Clear();
			DeathPos.Clear();
			Hud.Hide();
			ResetHold();
		}

		private static void HostReceive(ulong sender, byte[] data, long now)
		{
			byte version;
			Msg msg = Wire.TryDecode(data, out version);
			if (msg == null)
			{
				if (version != 0 && version != 2)
				{
					Log.WarnOnce("Lifeline.Version." + sender, "Lifeline: a player runs another Lifeline version (protocol " + version + "); everyone needs the same one.");
				}
			}
			else
			{
				if (!Wire.IsClientToHost(msg.Kind))
				{
					return;
				}
				Known.Add(sender);
				if (!(msg is HelloMsg))
				{
					if (!(msg is BuyMsg))
					{
						if (!(msg is AckMsg ackMsg))
						{
							if (msg is RequestMsg requestMsg)
							{
								HostRequest(sender, requestMsg.Slot, now);
							}
							return;
						}
						_host.OnAck(sender, ackMsg.Seq, ackMsg.StillDead, now);
						if (_cfg.DebugLog.Value)
						{
							Log.Info("Lifeline: ack from " + sender + " for revive " + ackMsg.Seq + (ackMsg.StillDead ? " (still dead there: resending)" : ""));
						}
					}
					else
					{
						HostBuy(sender);
					}
				}
				else
				{
					Net.ToClients(Wire.Encode(new RulesMsg
					{
						Rules = _host.Rules
					}), new ulong[1] { sender });
					Net.ToClients(Wire.Encode(new ChargesMsg
					{
						Count = (byte)Mathf.Min(255, _host.Charges)
					}), new ulong[1] { sender });
				}
			}
		}

		private static void HostRequest(ulong sender, int target, long now)
		{
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = PlayerOfClient(sender);
			PlayerControllerB val2 = PlayerAt(target);
			Refusal refusal = Refusal.Unknown;
			Vec3? at = null;
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
			{
				Vector3? val3 = BodyPosition(val2);
				if (!val3.HasValue && _host.Rules.AllowTombs && _host.TryDeath(target, out var d))
				{
					at = d.Position;
				}
				else if (val3.HasValue)
				{
					at = V(val3.Value);
				}
				refusal = _host.Check(target, val2.isPlayerDead, !val.isPlayerDead && val.isPlayerControlled, V(((Component)val).transform.position), at, now);
			}
			if (refusal != Refusal.None || !at.HasValue)
			{
				Net.ToClients(Wire.Encode(new RefusedMsg
				{
					Slot = (byte)target,
					Reason = refusal
				}), new ulong[1] { sender });
				if (_cfg.DebugLog.Value)
				{
					Log.Info("Lifeline: revive of " + target + " refused: " + refusal);
				}
				return;
			}
			bool isInsideFactory = val.isInsideFactory;
			bool isInHangarShipRoom = val.isInHangarShipRoom;
			Vector3 navMeshPosition = default(Vector3);
			((Vector3)(ref navMeshPosition))..ctor(at.Value.X, at.Value.Y, at.Value.Z);
			if (!isInHangarShipRoom && (Object)(object)RoundManager.Instance != (Object)null)
			{
				navMeshPosition = RoundManager.Instance.GetNavMeshPosition(navMeshPosition, default(NavMeshHit), 2.5f, -1);
			}
			int charges = _host.Charges;
			ReviveOrder reviveOrder = _host.Commit(target, V(navMeshPosition), isInsideFactory, isInHangarShipRoom, ToArray(Known), now);
			Net.ToClients(ReviveHost.Order(reviveOrder), Net.AllClients());
			if (_host.Charges != charges)
			{
				Net.ToClients(Wire.Encode(new ChargesMsg
				{
					Count = (byte)Mathf.Min(255, _host.Charges)
				}), Net.AllClients());
				Log.Info("Lifeline: a defibrillator charge was used (" + _host.Charges + " left)");
			}
			Log.Info("Lifeline: " + val.playerUsername + " revives " + val2.playerUsername + " (order " + reviveOrder.Seq + ")");
		}

		private static void HostBuy(ulong sender)
		{
			ReviveRules rules = _host.Rules;
			PlayerControllerB val = PlayerOfClient(sender);
			if (!rules.DefibEnabled)
			{
				Net.ToClients(Wire.Encode(new RefusedMsg
				{
					Slot = byte.MaxValue,
					Reason = Refusal.DefibOff
				}), new ulong[1] { sender });
				return;
			}
			Terminal val2 = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val2 == (Object)null || val2.groupCredits < rules.DefibPrice)
			{
				Net.ToClients(Wire.Encode(new RefusedMsg
				{
					Slot = byte.MaxValue,
					Reason = Refusal.NotEnoughCredits
				}), new ulong[1] { sender });
				return;
			}
			val2.groupCredits -= rules.DefibPrice;
			val2.SyncGroupCreditsClientRpc(val2.groupCredits, val2.numberOfItemsInDropship);
			_host.AddCharge();
			Net.ToClients(Wire.Encode(new ChargesMsg
			{
				Count = (byte)Mathf.Min(255, _host.Charges),
				Bought = (byte)(((Object)(object)val == (Object)null) ? 255u : val.playerClientId)
			}), Net.AllClients());
			Log.Info("Lifeline: " + (val?.playerUsername ?? "someone") + " bought a defibrillator charge (" + _host.Charges + " now)");
		}

		private static void ClientReceive(byte[] data, long now)
		{
			byte version;
			Msg msg = Wire.TryDecode(data, out version);
			if (!(msg is RulesMsg rulesMsg))
			{
				if (!(msg is ApplyMsg applyMsg))
				{
					if (msg is StateMsg state)
					{
						foreach (ReviveOrder item in Client.Reconcile(state, (int slot) => !AliveHere(slot)))
						{
							ApplyAndAck(item, now, reconcile: true);
						}
						return;
					}
					if (!(msg is RefusedMsg refusedMsg))
					{
						if (msg is ChargesMsg chargesMsg)
						{
							int charges = _charges;
							_charges = chargesMsg.Count;
							if (chargesMsg.Bought != byte.MaxValue && (Object)(object)PlayerAt(chargesMsg.Bought) != (Object)null)
							{
								Hud.Toast(PlayerAt(chargesMsg.Bought).playerUsername + " bought a defibrillator charge (" + chargesMsg.Count + " now)", 3f);
							}
							else if (chargesMsg.Count < charges)
							{
								Hud.Toast("Defibrillator used (" + chargesMsg.Count + " left)", 3f);
							}
						}
					}
					else
					{
						Hud.Toast(Refusals.Text(refusedMsg.Reason), 3f);
					}
				}
				else
				{
					ApplyAndAck(applyMsg.Order, now);
				}
			}
			else
			{
				Client.Rules = rulesMsg.Rules;
				_hostAnswered = true;
			}
		}

		private static void ApplyAndAck(ReviveOrder o, long now, bool reconcile = false)
		{
			bool deadHere = !AliveHere(o.Slot);
			if (Client.ShouldApply(o, deadHere, now))
			{
				if (reconcile)
				{
					Log.Info("Lifeline: player " + o.Slot + " is alive on the host but dead here: applying revive " + o.Seq + " again");
				}
				ReviveApplier.Apply(o);
			}
			Net.ToServer(new AckMsg
			{
				Seq = o.Seq,
				Slot = o.Slot,
				StillDead = !AliveHere(o.Slot)
			});
		}

		private static void UpdateTombs()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			for (int i = 0; i < instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = instance.allPlayerScripts[i];
				if ((Object)(object)val != (Object)null && val.isPlayerDead && !val.disconnectedMidGame && Client.Rules.AllowTombs && _hostAnswered && !BodyPosition(val).HasValue && DeathPos.ContainsKey(i))
				{
					Tombs.Show(i, DeathPos[i]);
				}
				else
				{
					Tombs.Remove(i);
				}
			}
		}

		private static void Interact()
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead || !localPlayerController.isPlayerControlled || !_hostAnswered || localPlayerController.inTerminalMenu || localPlayerController.isTypingChat || ((Object)(object)localPlayerController.quickMenuManager != (Object)null && localPlayerController.quickMenuManager.isMenuOpen))
			{
				ResetHold();
				Hud.Prompt(null, 0f);
				return;
			}
			ReviveRules rules = Client.Rules;
			Transform transform = ((Component)localPlayerController.gameplayCamera).transform;
			int num = -1;
			float num2 = float.MaxValue;
			StartOfRound instance = StartOfRound.Instance;
			for (int i = 0; i < instance.allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = instance.allPlayerScripts[i];
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)localPlayerController || !val.isPlayerDead || val.disconnectedMidGame)
				{
					continue;
				}
				Vector3? val2 = BodyPosition(val);
				if (!val2.HasValue && rules.AllowTombs && Tombs.TryGet(i, out var pos))
				{
					val2 = pos + Vector3.up * 0.5f;
				}
				if (!val2.HasValue)
				{
					continue;
				}
				float num3 = Vector3.Distance(((Component)localPlayerController).transform.position, val2.Value);
				if (!(num3 > rules.MaxDistance))
				{
					Vector3 val3 = val2.Value - transform.position;
					Vector3 normalized = ((Vector3)(ref val3)).normalized;
					if (!(Vector3.Dot(transform.forward, normalized) < 0.25f) && num3 < num2)
					{
						num2 = num3;
						num = i;
					}
				}
			}
			if (num != _target)
			{
				_target = num;
				_progress = 0f;
			}
			if (num < 0)
			{
				Hud.Prompt(null, 0f);
				return;
			}
			string playerUsername = instance.allPlayerScripts[num].playerUsername;
			if (Time.realtimeSinceStartup < _cooldownUntil)
			{
				Hud.Prompt("Reviving " + playerUsername + "...", 1f);
				return;
			}
			if (ReviveInput.Held)
			{
				_progress += Time.deltaTime / Mathf.Max(0.1f, rules.HoldSeconds);
			}
			else
			{
				_progress = 0f;
			}
			if (_progress >= 1f)
			{
				Net.ToServer(new RequestMsg
				{
					Slot = (byte)num
				});
				_cooldownUntil = Time.realtimeSinceStartup + 1.5f;
				_progress = 0f;
				if (_cfg.DebugLog.Value)
				{
					Log.Info("Lifeline: revive request for player " + num);
				}
			}
			Hud.Prompt("Hold [" + ReviveInput.Label + "] to revive " + playerUsername, _progress);
		}

		private static void ResetHold()
		{
			_target = -1;
			_progress = 0f;
		}

		internal static Vector3? BodyPosition(PlayerControllerB p)
		{
			//IL_0040: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			DeadBodyInfo deadBody = p.deadBody;
			if ((Object)(object)deadBody == (Object)null || !((Component)deadBody).gameObject.activeInHierarchy)
			{
				return null;
			}
			if ((Object)(object)deadBody.grabBodyObject != (Object)null)
			{
				return ((Component)deadBody.grabBodyObject).transform.position;
			}
			if (deadBody.bodyParts != null && deadBody.bodyParts.Length != 0 && (Object)(object)deadBody.bodyParts[0] != (Object)null)
			{
				return deadBody.bodyParts[0].position;
			}
			return ((Component)deadBody).transform.position;
		}

		private static bool AliveHere(int slot)
		{
			PlayerControllerB val = PlayerAt(slot);
			if ((Object)(object)val != (Object)null)
			{
				return !val.isPlayerDead;
			}
			return false;
		}

		private static PlayerControllerB? PlayerAt(int slot)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null || slot < 0 || slot >= instance.allPlayerScripts.Length)
			{
				return null;
			}
			return instance.allPlayerScripts[slot];
		}

		private static PlayerControllerB? PlayerOfClient(ulong clientId)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				return null;
			}
			PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val != (Object)null && val.actualClientId == clientId && (val.isPlayerControlled || val.isPlayerDead))
				{
					return val;
				}
			}
			return null;
		}

		private static int PlayerCount()
		{
			StartOfRound instance = StartOfRound.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				return instance.connectedPlayersAmount + 1;
			}
			return 1;
		}

		private static Vec3 V(Vector3 v)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			return new Vec3(v.x, v.y, v.z);
		}

		private static ulong[] ToArray(HashSet<ulong> set)
		{
			ulong[] array = new ulong[set.Count];
			set.CopyTo(array);
			return array;
		}
	}
	internal static class Tombs
	{
		private static readonly Dictionary<int, GameObject> Placed = new Dictionary<int, GameObject>();

		private static Material? _material;

		internal static bool TryGet(int slot, out Vector3 pos)
		{
			//IL_0001: 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)
			pos = default(Vector3);
			if (!Placed.TryGetValue(slot, out GameObject value) || (Object)(object)value == (Object)null)
			{
				return false;
			}
			pos = value.transform.position;
			return true;
		}

		internal static void Show(int slot, Vector3 deathPos)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			//IL_007e: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!Placed.TryGetValue(slot, out GameObject value) || !((Object)(object)value != (Object)null))
			{
				Vector3 position = deathPos;
				StartOfRound instance = StartOfRound.Instance;
				int num = (((Object)(object)instance != (Object)null) ? instance.collidersAndRoomMaskAndDefault : (-1));
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(deathPos + Vector3.up * 1.5f, Vector3.down, ref val, 30f, num, (QueryTriggerInteraction)1))
				{
					position = ((RaycastHit)(ref val)).point;
				}
				GameObject val2 = new GameObject("LifelineTomb" + slot);
				val2.transform.position = position;
				Part(val2, new Vector3(0f, 0.45f, 0f), new Vector3(0.55f, 0.9f, 0.14f));
				Part(val2, new Vector3(0f, 0.04f, 0f), new Vector3(0.75f, 0.08f, 0.3f));
				Placed[slot] = val2;
			}
		}

		internal static void Remove(int slot)
		{
			if (Placed.TryGetValue(slot, out GameObject value))
			{
				Placed.Remove(slot);
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
		}

		internal static void Clear()
		{
			foreach (GameObject value in Placed.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Placed.Clear();
		}

		private static void Part(GameObject root, Vector3 local, Vector3 scale)
		{
			//IL_002a: 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)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			Object.Destroy((Object)(object)val.GetComponent<Collider>());
			val.transform.SetParent(root.transform, false);
			val.transform.localPosition = local;
			val.transform.localScale = scale;
			Material val2 = Material();
			if ((Object)(object)val2 != (Object)null)
			{
				val.GetComponent<Renderer>().sharedMaterial = val2;
			}
		}

		private static Material? Material()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_material != (Object)null)
			{
				return _material;
			}
			Shader val = Shader.Find("HDRP/Lit");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			_material = new Material(val);
			_material.SetColor("_BaseColor", new Color(0.42f, 0.42f, 0.45f, 1f));
			return _material;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "dev.thatumi.Lifeline";

		public const string PLUGIN_NAME = "Lifeline";

		public const string PLUGIN_VERSION = "0.2.0";
	}
}
namespace Lifeline.Core
{
	public enum Kind : byte
	{
		Hello = 1,
		Request = 2,
		Ack = 3,
		Buy = 4,
		Rules = 20,
		Apply = 21,
		State = 22,
		Refused = 23,
		Charges = 24
	}
	public abstract class Msg
	{
		public abstract Kind Kind { get; }

		internal abstract void Write(PacketWriter w);

		internal abstract void Read(PacketReader r);
	}
	public sealed class HelloMsg : Msg
	{
		public override Kind Kind => Kind.Hello;

		internal override void Write(PacketWriter w)
		{
		}

		internal override void Read(PacketReader r)
		{
		}
	}
	public sealed class RequestMsg : Msg
	{
		public byte Slot;

		public override Kind Kind => Kind.Request;

		internal override void Write(PacketWriter w)
		{
			w.Byte(Slot);
		}

		internal override void Read(PacketReader r)
		{
			Slot = r.Byte();
		}
	}
	public sealed class AckMsg : Msg
	{
		public ushort Seq;

		public byte Slot;

		public bool StillDead;

		public override Kind Kind => Kind.Ack;

		internal override void Write(PacketWriter w)
		{
			w.USho