Decompiled source of CheepSave v1.0.2

plugins/CheepSave/CheepSave.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Rewired;
using RoR2;
using RoR2.UI;
using RoR2.UI.MainMenu;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CheepSave
{
	internal static class Banner
	{
		private static string message;

		private static float until;

		private static Canvas canvas;

		private static string shownKey;

		public static void Show(string text)
		{
			message = text;
			until = Time.unscaledTime + 6f;
		}

		public static void Update()
		{
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			CheepSaveData session = Loader.Session;
			bool flag = session != null && !Object.op_Implicit((Object)(object)Run.instance) && !Panel.IsOpen;
			bool flag2 = Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)Stage.instance) && !PauseScreenController.pauseScreenUp;
			bool flag3 = message != null && Time.unscaledTime < until && !Panel.IsOpen && !flag2;
			string text = ((!flag) ? "" : (Object.op_Implicit((Object)(object)PreGameController.instance) ? Loc.T("HINT_LOBBY") : (session.multiplayer ? Loc.T("HINT_MULTI") : "")));
			if (flag && !Object.op_Implicit((Object)(object)PreGameController.instance) && Time.frameCount != Panel.ClosedFrame && Pad.YDown())
			{
				Kit.Sound("Play_UI_menuClick");
				Loader.Cancel();
				return;
			}
			string text2 = (flag ? Pad.YGlyph() : "");
			string text3 = (flag ? (session.id + "|" + text + "|" + text2 + "|" + Language.currentLanguageName) : "") + "#" + (flag3 ? message : "");
			if (text3 == shownKey)
			{
				return;
			}
			shownKey = text3;
			if (Object.op_Implicit((Object)(object)canvas))
			{
				Object.Destroy((Object)(object)((Component)canvas).gameObject);
			}
			canvas = null;
			if (flag || flag3)
			{
				canvas = CursorFix.MakeCanvas("CheepSaveBanner", 31000);
				RectTransform croot = (RectTransform)((Component)canvas).transform;
				float num = Mathf.Min(1040f, CursorFix.Width - 40f);
				float num2 = 18f;
				if (flag)
				{
					RectTransform parent = Plate(croot, num, num2, 104f);
					((TMP_Text)Kit.Txt((Transform)(object)parent, string.Format(Loc.T("SELECTED"), Loader.StageText(session)), 24f, Kit.Teal, (TextAlignmentOptions)257, bold: true)).rectTransform.At(78f, 16f, num - 300f, 34f);
					((TMP_Text)Kit.Txt((Transform)(object)parent, text, 19f, Kit.Text, (TextAlignmentOptions)257, bold: false, wrap: true)).rectTransform.At(78f, 52f, num - 300f, 48f);
					((Component)Kit.Btn((Transform)(object)parent, (text2.Length > 0) ? (text2 + " " + Loc.T("CANCEL")) : Loc.T("CANCEL"), Kit.Card, Kit.Text, Loader.Cancel, 21f)).GetComponent<RectTransform>().At(num - 200f, 26f, 176f, 52f);
					num2 += 116f;
				}
				if (flag3)
				{
					((TMP_Text)Kit.Txt((Transform)(object)Plate(croot, num, num2, 72f), message, 20f, Kit.Text, (TextAlignmentOptions)4097, bold: false, wrap: true)).rectTransform.At(78f, 0f, num - 100f, 72f);
				}
			}
		}

		private static RectTransform Plate(RectTransform croot, float w, float y, float h)
		{
			//IL_0001: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((Graphic)Kit.Img((Transform)(object)croot, Kit.Surface, Kit.Round, raycast: true, "Plate")).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			rectTransform.anchorMax = val;
			rectTransform.anchorMin = val;
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = new Vector2(0f, 0f - y);
			rectTransform.sizeDelta = new Vector2(w, h);
			((Graphic)Kit.Img((Transform)(object)rectTransform, Kit.Stroke, Kit.Ring)).rectTransform.Fill();
			((Graphic)Kit.Img((Transform)(object)rectTransform, Kit.Teal, Kit.RoundSmall)).rectTransform.At(0f, 14f, 5f, h - 28f);
			((Graphic)Kit.Raw((Transform)(object)rectTransform, Kit.Tex("RoR2/Base/Common/MiscIcons/texRoR2Icon.png"), Kit.Teal)).rectTransform.At(24f, h / 2f - 18f, 36f, 36f);
			return rectTransform;
		}
	}
	internal static class Json
	{
		private sealed class Num
		{
			public string text;
		}

		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		public static string Write(object o)
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteValue(stringBuilder, o, 0);
			return stringBuilder.ToString();
		}

		public static T Read<T>(string s)
		{
			int i = 0;
			object node = Parse(s, ref i);
			return (T)Bind(typeof(T), node);
		}

		public static T Clone<T>(T o)
		{
			return Read<T>(Write(o));
		}

		private static void WriteValue(StringBuilder sb, object v, int ind)
		{
			if (v != null)
			{
				if (!(v is string s))
				{
					if (!(v is bool flag))
					{
						if (!(v is float num))
						{
							if (!(v is double num2))
							{
								if (!(v is int) && !(v is uint) && !(v is long) && !(v is ulong) && !(v is short) && !(v is ushort) && !(v is byte))
								{
									if (v is IList list)
									{
										if (list.Count == 0)
										{
											sb.Append("[]");
											return;
										}
										sb.Append('[');
										for (int i = 0; i < list.Count; i++)
										{
											sb.Append((i == 0) ? "\n" : ",\n").Append(' ', (ind + 1) * 2);
											WriteValue(sb, list[i], ind + 1);
										}
										sb.Append('\n').Append(' ', ind * 2).Append(']');
										return;
									}
									sb.Append('{');
									bool flag2 = true;
									FieldInfo[] fields = v.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
									foreach (FieldInfo fieldInfo in fields)
									{
										sb.Append(flag2 ? "\n" : ",\n").Append(' ', (ind + 1) * 2);
										flag2 = false;
										WriteString(sb, fieldInfo.Name);
										sb.Append(": ");
										WriteValue(sb, fieldInfo.GetValue(v), ind + 1);
									}
									sb.Append('\n').Append(' ', ind * 2).Append('}');
								}
								else
								{
									sb.Append(Convert.ToString(v, Inv));
								}
							}
							else
							{
								sb.Append(num2.ToString("R", Inv));
							}
						}
						else
						{
							sb.Append(num.ToString("R", Inv));
						}
					}
					else
					{
						sb.Append(flag ? "true" : "false");
					}
				}
				else
				{
					WriteString(sb, s);
				}
			}
			else
			{
				sb.Append("null");
			}
		}

		private static void WriteString(StringBuilder sb, string s)
		{
			sb.Append('"');
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
					sb.Append("\\\"");
					continue;
				case '\\':
					sb.Append("\\\\");
					continue;
				case '\n':
					sb.Append("\\n");
					continue;
				case '\r':
					sb.Append("\\r");
					continue;
				case '\t':
					sb.Append("\\t");
					continue;
				}
				if (c < ' ')
				{
					StringBuilder stringBuilder = sb.Append("\\u");
					int num = c;
					stringBuilder.Append(num.ToString("x4"));
				}
				else
				{
					sb.Append(c);
				}
			}
			sb.Append('"');
		}

		private static void SkipWs(string s, ref int i)
		{
			while (i < s.Length && char.IsWhiteSpace(s[i]))
			{
				i++;
			}
		}

		private static object Parse(string s, ref int i)
		{
			SkipWs(s, ref i);
			if (i >= s.Length)
			{
				throw new FormatException("Unexpected end of JSON");
			}
			char c = s[i];
			switch (c)
			{
			case '{':
			{
				Dictionary<string, object> dictionary = new Dictionary<string, object>();
				i++;
				SkipWs(s, ref i);
				if (s[i] == '}')
				{
					i++;
					return dictionary;
				}
				while (true)
				{
					SkipWs(s, ref i);
					string key = ParseString(s, ref i);
					SkipWs(s, ref i);
					if (s[i] != ':')
					{
						throw new FormatException("':' expected at " + i);
					}
					i++;
					dictionary[key] = Parse(s, ref i);
					SkipWs(s, ref i);
					if (s[i] != ',')
					{
						break;
					}
					i++;
				}
				if (s[i] == '}')
				{
					i++;
					return dictionary;
				}
				throw new FormatException("',' or '}' expected at " + i);
			}
			case '[':
			{
				List<object> list = new List<object>();
				i++;
				SkipWs(s, ref i);
				if (s[i] == ']')
				{
					i++;
					return list;
				}
				while (true)
				{
					list.Add(Parse(s, ref i));
					SkipWs(s, ref i);
					if (s[i] != ',')
					{
						break;
					}
					i++;
				}
				if (s[i] == ']')
				{
					i++;
					return list;
				}
				throw new FormatException("',' or ']' expected at " + i);
			}
			case '"':
				return ParseString(s, ref i);
			default:
			{
				if (s.Length - i >= 4 && string.CompareOrdinal(s, i, "null", 0, 4) == 0)
				{
					i += 4;
					return null;
				}
				if (s.Length - i >= 4 && string.CompareOrdinal(s, i, "true", 0, 4) == 0)
				{
					i += 4;
					return true;
				}
				if (s.Length - i >= 5 && string.CompareOrdinal(s, i, "false", 0, 5) == 0)
				{
					i += 5;
					return false;
				}
				int num = i;
				while (i < s.Length && "+-0123456789.eE".IndexOf(s[i]) >= 0)
				{
					i++;
				}
				if (i == num)
				{
					throw new FormatException("Unexpected '" + c + "' at " + i);
				}
				return new Num
				{
					text = s.Substring(num, i - num)
				};
			}
			}
		}

		private static string ParseString(string s, ref int i)
		{
			if (s[i] != '"')
			{
				throw new FormatException("'\"' expected at " + i);
			}
			i++;
			StringBuilder stringBuilder = new StringBuilder();
			while (i < s.Length)
			{
				char c = s[i++];
				switch (c)
				{
				case '"':
					return stringBuilder.ToString();
				default:
					stringBuilder.Append(c);
					break;
				case '\\':
				{
					char c2 = s[i++];
					switch (c2)
					{
					case 'n':
						stringBuilder.Append('\n');
						break;
					case 'r':
						stringBuilder.Append('\r');
						break;
					case 't':
						stringBuilder.Append('\t');
						break;
					case 'b':
						stringBuilder.Append('\b');
						break;
					case 'f':
						stringBuilder.Append('\f');
						break;
					case 'u':
						stringBuilder.Append((char)Convert.ToInt32(s.Substring(i, 4), 16));
						i += 4;
						break;
					default:
						stringBuilder.Append(c2);
						break;
					}
					break;
				}
				}
			}
			throw new FormatException("Unterminated string");
		}

		private static object Bind(Type t, object node)
		{
			if (node == null)
			{
				if (!t.IsValueType)
				{
					return null;
				}
				return Activator.CreateInstance(t);
			}
			if (t == typeof(string))
			{
				object obj;
				if (!(node is Num num))
				{
					obj = node as string;
					if (obj == null)
					{
						return node.ToString();
					}
				}
				else
				{
					obj = num.text;
				}
				return obj;
			}
			if (t == typeof(bool))
			{
				bool flag = default(bool);
				int num2;
				if (node is bool)
				{
					flag = (bool)node;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				return (byte)((uint)num2 & (flag ? 1u : 0u)) != 0;
			}
			if (node is Num num3)
			{
				if (t == typeof(float))
				{
					return float.Parse(num3.text, NumberStyles.Float, Inv);
				}
				if (t == typeof(double))
				{
					return double.Parse(num3.text, NumberStyles.Float, Inv);
				}
				return Convert.ChangeType(decimal.Parse(num3.text, NumberStyles.Float, Inv), t, Inv);
			}
			if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>))
			{
				IList list = (IList)Activator.CreateInstance(t);
				Type t2 = t.GetGenericArguments()[0];
				if (node is List<object> list2)
				{
					foreach (object item in list2)
					{
						list.Add(Bind(t2, item));
					}
				}
				return list;
			}
			object obj2 = Activator.CreateInstance(t);
			if (node is Dictionary<string, object> dictionary)
			{
				FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (dictionary.TryGetValue(fieldInfo.Name, out var value))
					{
						fieldInfo.SetValue(obj2, Bind(fieldInfo.FieldType, value));
					}
				}
			}
			return obj2;
		}
	}
	internal static class Kit
	{
		public static readonly Color Ink = Color32.op_Implicit(new Color32((byte)7, (byte)10, (byte)14, (byte)200));

		public static readonly Color Surface = Color32.op_Implicit(new Color32((byte)14, (byte)19, (byte)26, (byte)252));

		public static readonly Color Card = Color32.op_Implicit(new Color32((byte)23, (byte)30, (byte)40, byte.MaxValue));

		public static readonly Color CardHover = Color32.op_Implicit(new Color32((byte)31, (byte)41, (byte)54, byte.MaxValue));

		public static readonly Color Stroke = Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)20));

		public static readonly Color Teal = Color32.op_Implicit(new Color32((byte)79, (byte)209, (byte)197, byte.MaxValue));

		public static readonly Color TealDim = Color32.op_Implicit(new Color32((byte)79, (byte)209, (byte)197, (byte)40));

		public static readonly Color Amber = Color32.op_Implicit(new Color32((byte)242, (byte)184, (byte)75, byte.MaxValue));

		public static readonly Color Violet = Color32.op_Implicit(new Color32((byte)214, (byte)140, (byte)230, byte.MaxValue));

		public static readonly Color Text = Color32.op_Implicit(new Color32((byte)232, (byte)237, (byte)242, byte.MaxValue));

		public static readonly Color Muted = Color32.op_Implicit(new Color32((byte)134, (byte)148, (byte)163, byte.MaxValue));

		public static readonly Color Danger = Color32.op_Implicit(new Color32((byte)229, (byte)83, (byte)75, byte.MaxValue));

		private static Sprite round;

		private static Sprite roundSmall;

		private static Sprite ring;

		private static Sprite gradRight;

		private static Sprite gradUp;

		private static Sprite gear;

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

		public const string IconMoney = "RoR2/Base/Common/MiscIcons/texRuleBonusStartingMoney.png";

		public const string IconVoidCoin = "RoR2/DLC1/VoidCoin/texVoidCoinIcon.png";

		public const string IconStage = "RoR2/Base/Common/MiscIcons/texTeleporterIconOutlined.png";

		public const string IconLoop = "RoR2/Base/Achievements/texLoopOnceIcon.png";

		public const string IconItems = "RoR2/Base/Common/MiscIcons/texInventoryIconOutlined.png";

		public const string IconEquipment = "RoR2/Base/Common/MiscIcons/texLootIconOutlined.png";

		public const string IconDrone = "RoR2/Base/Common/MiscIcons/texDroneIconOutlined.png";

		public const string IconRoR2 = "RoR2/Base/Common/MiscIcons/texRoR2Icon.png";

		public const string IconTime = "RoR2/DLC3/UI/texTempItemsTimer.png";

		public const string IconLevel = "RoR2/Base/Common/MiscIcons/texTeleporterCharge.png";

		public const string IconPlayers = "RoR2/Base/UI/texCrownIcon.png";

		public const string IconMystery = "RoR2/Base/Common/MiscIcons/texMysteryIcon.png";

		public const string IconArtifact = "RoR2/Base/Common/MiscIcons/texUnlockIcon.png";

		public const string BgEquipment = "RoR2/Base/Common/texEquipmentBGIcon.png";

		public const string BgLunar = "RoR2/Base/Common/texLunarBGIcon.png";

		public const string BgSurvivor = "RoR2/Base/Common/texSurvivorBGIcon.png";

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

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

		public static Sprite Round
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)round))
				{
					return round = MakeRound(64, 16f, 0f);
				}
				return round;
			}
		}

		public static Sprite RoundSmall
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)roundSmall))
				{
					return roundSmall = MakeRound(32, 7f, 0f);
				}
				return roundSmall;
			}
		}

		public static Sprite Ring
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)ring))
				{
					return ring = MakeRound(64, 16f, 2.2f);
				}
				return ring;
			}
		}

		public static Sprite GradRight
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)gradRight))
				{
					return gradRight = MakeGrad(horizontal: true);
				}
				return gradRight;
			}
		}

		public static Sprite GradUp
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)gradUp))
				{
					return gradUp = MakeGrad(horizontal: false);
				}
				return gradUp;
			}
		}

		public static Sprite Gear
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)gear))
				{
					return gear = MakeGear(96, 8);
				}
				return gear;
			}
		}

		private static Sprite MakeRound(int size, float radius, float ringWidth)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				wrapMode = (TextureWrapMode)1
			};
			float num = (float)size / 2f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = Mathf.Abs((float)j + 0.5f - num) - (num - radius);
					float num3 = Mathf.Abs((float)i + 0.5f - num) - (num - radius);
					Vector2 val2 = new Vector2(Mathf.Max(num2, 0f), Mathf.Max(num3, 0f));
					float num4 = ((Vector2)(ref val2)).magnitude + Mathf.Min(Mathf.Max(num2, num3), 0f) - radius;
					float num5 = Mathf.Clamp01(0.5f - num4);
					if (ringWidth > 0f)
					{
						num5 *= Mathf.Clamp01(num4 + ringWidth + 0.5f);
					}
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num5));
				}
			}
			val.Apply();
			float num6 = radius + 1f;
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(num6, num6, num6, num6));
		}

		private static Sprite MakeGear(int size, int teeth)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				wrapMode = (TextureWrapMode)1
			};
			float num = (float)size / 2f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num2 = ((float)j + 0.5f - num) / num;
					float num3 = ((float)i + 0.5f - num) / num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(-0.2f, 0.2f, Mathf.Cos(Mathf.Atan2(num3, num2) * (float)teeth)));
					float num6 = Mathf.Clamp01((Mathf.Lerp(0.7f, 0.97f, num5) - num4) * num + 0.5f) * Mathf.Clamp01((num4 - 0.3f) * num + 0.5f);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f));
		}

		private static Sprite MakeGrad(bool horizontal)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00b5: 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_0080: 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)
			Texture2D val = new Texture2D((!horizontal) ? 1 : 128, horizontal ? 1 : 128, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				wrapMode = (TextureWrapMode)1
			};
			for (int i = 0; i < 128; i++)
			{
				float num = (float)i / 127f;
				float num2 = Mathf.SmoothStep(1f, 0f, num);
				if (horizontal)
				{
					val.SetPixel(i, 0, new Color(1f, 1f, 1f, num2));
				}
				else
				{
					val.SetPixel(0, i, new Color(1f, 1f, 1f, num2));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		public static Texture Tex(string key)
		{
			//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)
			if (texCache.TryGetValue(key, out var value))
			{
				return value;
			}
			try
			{
				value = (Texture)(object)Addressables.LoadAssetAsync<Texture2D>((object)key).WaitForCompletion();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon " + key + ": " + ex.Message));
			}
			texCache[key] = value;
			return value;
		}

		public static Sprite SpriteOf(Sprite direct, AssetReferenceT<Sprite> reference)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)direct))
			{
				return direct;
			}
			if (reference == null || !((AssetReference)reference).RuntimeKeyIsValid())
			{
				return null;
			}
			string text = ((AssetReference)reference).RuntimeKey.ToString();
			if (spriteCache.TryGetValue(text, out var value))
			{
				return value;
			}
			try
			{
				value = Addressables.LoadAssetAsync<Sprite>(((AssetReference)reference).RuntimeKey).WaitForCompletion();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Icon " + text + ": " + ex.Message));
			}
			spriteCache[text] = value;
			return value;
		}

		public static Texture ScenePreview(string sceneName)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (previews.TryGetValue(sceneName, out var value))
			{
				return value;
			}
			SceneDef sceneDefFromSceneName = SceneCatalog.GetSceneDefFromSceneName(sceneName);
			if (Object.op_Implicit((Object)(object)sceneDefFromSceneName))
			{
				value = sceneDefFromSceneName.previewTexture;
				if (!Object.op_Implicit((Object)(object)value) && sceneDefFromSceneName.previewTextureReference != null && ((AssetReference)sceneDefFromSceneName.previewTextureReference).RuntimeKeyIsValid())
				{
					try
					{
						value = Addressables.LoadAssetAsync<Texture>(((AssetReference)sceneDefFromSceneName.previewTextureReference).RuntimeKey).WaitForCompletion();
					}
					catch (Exception ex)
					{
						Plugin.Log.LogWarning((object)("Preview " + sceneName + ": " + ex.Message));
					}
				}
			}
			previews[sceneName] = value;
			return value;
		}

		public static void Sound(string name)
		{
			if (Object.op_Implicit((Object)(object)RoR2Application.instance))
			{
				Util.PlaySound(name, ((Component)RoR2Application.instance).gameObject);
			}
		}

		public static RectTransform Node(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_0020: 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_0038: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = 5
			};
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		public static RectTransform At(this RectTransform r, float x, float y, float w, float h)
		{
			//IL_0013: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			r.anchorMax = val;
			r.anchorMin = val;
			r.pivot = new Vector2(0f, 1f);
			r.anchoredPosition = new Vector2(x, 0f - y);
			r.sizeDelta = new Vector2(w, h);
			return r;
		}

		public static RectTransform Fill(this RectTransform r, float left = 0f, float top = 0f, float right = 0f, float bottom = 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_002f: 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)
			r.anchorMin = Vector2.zero;
			r.anchorMax = Vector2.one;
			r.pivot = new Vector2(0.5f, 0.5f);
			r.offsetMin = new Vector2(left, bottom);
			r.offsetMax = new Vector2(0f - right, 0f - top);
			return r;
		}

		public static Image Img(Transform parent, Color c, Sprite s = null, bool raycast = false, string name = "Image")
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)Node(parent, name)).gameObject.AddComponent<Image>();
			obj.sprite = s;
			obj.type = (Type)((Object.op_Implicit((Object)(object)s) && s.border != Vector4.zero) ? 1 : 0);
			((Graphic)obj).color = c;
			((Graphic)obj).raycastTarget = raycast;
			return obj;
		}

		public static RawImage Raw(Transform parent, Texture t, Color? c = null)
		{
			//IL_0032: 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)
			RawImage val = ((Component)Node(parent, "Icon")).gameObject.AddComponent<RawImage>();
			val.texture = t;
			((Graphic)val).color = (Color)(((??)c) ?? Color.white);
			((Graphic)val).raycastTarget = false;
			if (!Object.op_Implicit((Object)(object)t))
			{
				((Behaviour)val).enabled = false;
			}
			return val;
		}

		public static RawImage Icon(Transform parent, Sprite s, Color? c = null)
		{
			//IL_002f: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			RawImage val = Raw(parent, (Texture)(object)(Object.op_Implicit((Object)(object)s) ? s.texture : null), c);
			if (Object.op_Implicit((Object)(object)s) && Object.op_Implicit((Object)(object)s.texture))
			{
				Rect textureRect = s.textureRect;
				float num = ((Texture)s.texture).width;
				float num2 = ((Texture)s.texture).height;
				val.uvRect = new Rect(((Rect)(ref textureRect)).x / num, ((Rect)(ref textureRect)).y / num2, ((Rect)(ref textureRect)).width / num, ((Rect)(ref textureRect)).height / num2);
			}
			return val;
		}

		public static RawImage Cover(Transform parent, Texture t, float w, float h)
		{
			//IL_0083: 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)
			RawImage val = Raw(parent, t);
			if (Object.op_Implicit((Object)(object)t) && t.width > 0 && t.height > 0)
			{
				float num = (float)t.width / (float)t.height;
				float num2 = w / h;
				val.uvRect = ((num > num2) ? new Rect((1f - num2 / num) / 2f, 0f, num2 / num, 1f) : new Rect(0f, (1f - num / num2) / 2f, 1f, num / num2));
			}
			return val;
		}

		public static TextMeshProUGUI Txt(Transform parent, string s, float size, Color c, TextAlignmentOptions align = (TextAlignmentOptions)257, bool bold = false, bool wrap = false)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			HGTextMeshProUGUI obj = ((Component)Node(parent, "Text")).gameObject.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)obj).text = s;
			((TMP_Text)obj).fontSize = size;
			((Graphic)obj).color = c;
			((TMP_Text)obj).alignment = align;
			((TMP_Text)obj).fontStyle = (FontStyles)(bold ? 1 : 0);
			((TMP_Text)obj).enableWordWrapping = wrap;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)(!wrap);
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).richText = true;
			return (TextMeshProUGUI)(object)obj;
		}

		public static RectTransform Masked(Transform parent, Color c, string name = "Card")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Image obj = Img(parent, c, Round, raycast: false, name);
			((Component)obj).gameObject.AddComponent<Mask>().showMaskGraphic = true;
			return ((Graphic)obj).rectTransform;
		}

		public static Button Btn(Transform parent, string label, Color bg, Color fg, Action onClick, float size = 22f, Sprite shape = null)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			Image val = Img(parent, Color.white, Object.op_Implicit((Object)(object)shape) ? shape : Round, raycast: true, "Button");
			Button obj = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)val;
			ColorBlock colors = ((Selectable)obj).colors;
			((ColorBlock)(ref colors)).normalColor = bg;
			((ColorBlock)(ref colors)).highlightedColor = Color.Lerp(bg, Color.white, 0.18f);
			((ColorBlock)(ref colors)).pressedColor = Color.Lerp(bg, Color.black, 0.2f);
			((ColorBlock)(ref colors)).selectedColor = bg;
			((ColorBlock)(ref colors)).disabledColor = new Color(bg.r, bg.g, bg.b, bg.a * 0.35f);
			((ColorBlock)(ref colors)).fadeDuration = 0.08f;
			((Selectable)obj).colors = colors;
			Navigation navigation = ((Selectable)obj).navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)obj).navigation = navigation;
			if (label != null)
			{
				((TMP_Text)Txt(((Component)val).transform, label, size, fg, (TextAlignmentOptions)514, bold: true)).rectTransform.Fill(10f, 0f, 10f);
			}
			((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
			{
				Sound("Play_UI_menuClick");
				onClick?.Invoke();
			});
			((Component)val).gameObject.AddComponent<HoverSound>();
			return obj;
		}

		public static void Tip(Graphic g, string text)
		{
			g.raycastTarget = true;
			((Component)g).gameObject.AddComponent<TipTrigger>().text = text;
		}
	}
	internal class HoverSound : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler
	{
		public void OnPointerEnter(PointerEventData e)
		{
			Button component = ((Component)this).GetComponent<Button>();
			if (Object.op_Implicit((Object)(object)component) && ((Selectable)component).interactable)
			{
				Kit.Sound("Play_UI_menuHover");
			}
		}
	}
	internal class TipTrigger : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public string text;

		public void OnPointerEnter(PointerEventData e)
		{
			Panel.ShowTip(text);
		}

		public void OnPointerExit(PointerEventData e)
		{
			Panel.ShowTip(null);
		}

		private void OnDisable()
		{
			Panel.ShowTip(null);
		}
	}
	internal static class CursorFix
	{
		public const int CursorOrder = 32700;

		public static float Width
		{
			get
			{
				if (Screen.height <= 0)
				{
					return 1920f;
				}
				return 1080f * (float)Screen.width / (float)Screen.height;
			}
		}

		public static void Apply()
		{
			CursorIndicatorController[] array = Object.FindObjectsOfType<CursorIndicatorController>();
			foreach (CursorIndicatorController val in array)
			{
				Canvas val2 = ((Component)val).GetComponentInParent<Canvas>();
				if (!Object.op_Implicit((Object)(object)val2))
				{
					val2 = ((Component)val).gameObject.AddComponent<Canvas>();
					val2.renderMode = (RenderMode)0;
				}
				if (!val2.isRootCanvas)
				{
					val2.overrideSorting = true;
				}
				if (val2.sortingOrder < 32700)
				{
					val2.sortingOrder = 32700;
				}
			}
		}

		public static Canvas MakeCanvas(string name, int order)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			Object.DontDestroyOnLoad((Object)val);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = order;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.screenMatchMode = (ScreenMatchMode)0;
			obj.matchWidthOrHeight = 1f;
			val.AddComponent<GraphicRaycaster>();
			Apply();
			return val2;
		}
	}
	internal static class Loader
	{
		private class PendingMinions
		{
			public CharacterMaster master;

			public List<MinionData> list;

			public float bodySeenAt = -1f;

			public float until;
		}

		private static bool sessionCheckedInLobby;

		private static float nextEnforce;

		private static CheepSaveData restoring;

		private static Dictionary<string, PlayerData> map;

		private static readonly List<PendingMinions> minionQueue = new List<PendingMinions>();

		private static bool announceLoaded;

		private static ulong pendingTeamExp;

		public static CheepSaveData Session { get; private set; }

		public static bool IsRestoring => restoring != null;

		public static CheepSaveData Restoring => restoring;

		public static void ApplyTeamExp()
		{
			if (pendingTeamExp != 0L && NetworkServer.active && Object.op_Implicit((Object)(object)TeamManager.instance))
			{
				ulong teamExperience = TeamManager.instance.GetTeamExperience((TeamIndex)1);
				if (pendingTeamExp > teamExperience)
				{
					TeamManager.instance.GiveTeamExperience((TeamIndex)1, pendingTeamExp - teamExperience);
				}
				Plugin.Log.LogInfo((object)("Team level restored: " + TeamManager.instance.GetTeamLevel((TeamIndex)1)));
				pendingTeamExp = 0uL;
			}
		}

		public static void Msg(string text)
		{
			Chat.AddMessage("<color=#e5c962>[CheepSave]</color> " + text);
			Banner.Show(text);
		}

		public static string StageText(CheepSaveData d)
		{
			return string.Format(Loc.T("STAGE_OF"), d.stageClearCount + 1, Snapshot.SceneTitle(d.sceneName));
		}

		public static bool SaveNow()
		{
			Run instance = Run.instance;
			if (!NetworkServer.active)
			{
				Msg(Loc.T("HOST_ONLY"));
				return false;
			}
			if (!Snapshot.IsSupported(instance))
			{
				Msg(Loc.T("UNSUPPORTED"));
				return false;
			}
			if (Snapshot.Current == null)
			{
				Msg(Loc.T("NOTHING"));
				return false;
			}
			try
			{
				CheepSaveData cheepSaveData = Json.Clone(Snapshot.Current);
				if (!Plugin.StageStartOnly.Value)
				{
					Snapshot.CaptureProgress(instance, cheepSaveData);
				}
				else
				{
					cheepSaveData.savedAtUtc = DateTime.UtcNow.ToString("o");
				}
				SaveStore.Write(cheepSaveData);
				Msg(string.Format(Loc.T("SAVED"), StageText(cheepSaveData)));
				Plugin.Log.LogInfo((object)("Saved " + cheepSaveData.id + ": " + cheepSaveData.sceneName + ", stage " + (cheepSaveData.stageClearCount + 1) + ", players " + cheepSaveData.players.Count));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Save failed: " + ex));
				Msg(string.Format(Loc.T("ERROR"), ex.Message));
				return false;
			}
		}

		public static void OnServerGameOver(Run run, GameEndingDef ending)
		{
			if (!NetworkServer.active || !Snapshot.IsSupported(run) || string.IsNullOrEmpty(Snapshot.RunId) || !Object.op_Implicit((Object)(object)ending))
			{
				return;
			}
			bool isWin = ending.isWin;
			if (!(isWin ? Plugin.DeleteOnWin.Value : Plugin.DeleteOnDeath.Value))
			{
				return;
			}
			Snapshot.Current = null;
			try
			{
				if (SaveStore.Delete(Snapshot.RunMultiplayer, Snapshot.RunId))
				{
					Msg(Loc.T(isWin ? "DELETED_WIN" : "DELETED_DEATH"));
					Plugin.Log.LogInfo((object)("Run ended (" + ending.cachedName + "), save deleted: " + Snapshot.RunId));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Deleting the save failed: " + ex));
			}
		}

		public static void Begin(CheepSaveData d)
		{
			Session = d;
			sessionCheckedInLobby = false;
			nextEnforce = 0f;
			Plugin.Log.LogInfo((object)("Load session: " + d.id + " (" + (d.multiplayer ? "multiplayer" : "singleplayer") + ")"));
		}

		public static void Cancel()
		{
			if (Session != null)
			{
				Session = null;
				Msg(Loc.T("CANCELLED"));
			}
		}

		public static void OnLobbyClosed()
		{
			if (Session != null && sessionCheckedInLobby && !Object.op_Implicit((Object)(object)Run.instance))
			{
				Session = null;
			}
		}

		private static bool CheckSessionInLobby(PreGameController pgc)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			CheepSaveData session = Session;
			if (!Object.op_Implicit((Object)(object)SceneCatalog.GetSceneDefFromSceneName(session.sceneName)))
			{
				Session = null;
				Msg(string.Format(Loc.T("LOAD_ERROR"), session.sceneName));
				return false;
			}
			if (session.multiplayer == RoR2Application.isInSinglePlayer)
			{
				Session = null;
				Msg(Loc.T(session.multiplayer ? "NEED_MULTI" : "NEED_SOLO"));
				return false;
			}
			if (session.gameMode != GameModeCatalog.GetGameModeName(pgc.gameModeIndex))
			{
				Session = null;
				Run val = GameModeCatalog.FindGameModePrefabComponent(session.gameMode);
				Msg(string.Format(Loc.T("WRONG_MODE"), Object.op_Implicit((Object)(object)val) ? Language.GetString(val.nameToken) : session.gameMode));
				return false;
			}
			if (ulong.TryParse(session.seed, out var result))
			{
				pgc.runSeed = result;
			}
			Msg(string.Format(Loc.T("SELECTED"), StageText(session)) + " " + Loc.T("HINT_LOBBY"));
			return true;
		}

		private static void EnforceLobby(PreGameController pgc)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (string rule in Session.rules)
			{
				RuleChoiceDef val = RuleCatalog.FindChoiceDef(rule);
				if (val != null && pgc.readOnlyRuleBook.GetRuleChoice(val.ruleDef.globalIndex) != val && pgc.ApplyChoice(val.globalIndex))
				{
					flag = true;
				}
			}
			if (flag)
			{
				pgc.RecalculateModifierAvailability();
			}
			Dictionary<string, PlayerData> dictionary = Snapshot.MapUsers(Session);
			foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
			{
				if (dictionary.TryGetValue(Snapshot.UserKey(readOnlyInstances.id), out var value))
				{
					Snapshot.SetBody(readOnlyInstances, value.body);
				}
			}
		}

		public static bool TryGetLockedBody(NetworkUser user, out BodyIndex body)
		{
			//IL_0039: 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_005b: Expected I4, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			body = (BodyIndex)(-1);
			if (Session == null || !sessionCheckedInLobby || !NetworkServer.active || !Object.op_Implicit((Object)(object)PreGameController.instance) || !Object.op_Implicit((Object)(object)user))
			{
				return false;
			}
			if (!Snapshot.MapUsers(Session).TryGetValue(Snapshot.UserKey(user.id), out var value))
			{
				return false;
			}
			body = (BodyIndex)(int)BodyCatalog.FindBodyIndex(value.body);
			if ((int)body != -1)
			{
				return Object.op_Implicit((Object)(object)SurvivorCatalog.GetSurvivorDef(SurvivorCatalog.GetSurvivorIndexFromBodyIndex(body)));
			}
			return false;
		}

		public static void OnRunStartPrefix(Run run)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (!NetworkServer.active)
			{
				return;
			}
			CheepSaveData session = Session;
			Session = null;
			if (session == null || !sessionCheckedInLobby || !Snapshot.IsSupported(run))
			{
				return;
			}
			restoring = session;
			map = Snapshot.MapUsers(session);
			try
			{
				RuleBook val = new RuleBook();
				val.Copy(run.ruleBook);
				foreach (string rule in session.rules)
				{
					RuleChoiceDef val2 = RuleCatalog.FindChoiceDef(rule);
					if (val2 != null)
					{
						val.ApplyChoice(val2);
					}
				}
				run.SetRuleBook(val);
				if (ulong.TryParse(session.seed, out var result))
				{
					run.seed = result;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Restoring rules failed: " + ex));
			}
		}

		public static void OnRunStartPostfix(Run run)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			if (restoring == null)
			{
				Snapshot.RunId = DateTime.Now.ToString("yyyyMMdd-HHmmss") + "-" + Guid.NewGuid().ToString("N").Substring(0, 6);
				Snapshot.RunMultiplayer = !RoR2Application.isInSinglePlayer;
				Snapshot.Capture(run, run.nextStageScene);
				return;
			}
			CheepSaveData cheepSaveData = restoring;
			restoring = null;
			Snapshot.RunId = cheepSaveData.id;
			Snapshot.RunMultiplayer = cheepSaveData.multiplayer;
			try
			{
				run.NetworkstageClearCount = cheepSaveData.stageClearCount;
				run.Network_loopClearCount = cheepSaveData.loopClearCount;
				run.NetworkstageClearCountAtLoopStart = cheepSaveData.stageClearCountAtLoopStart;
				run.shopPortalCount = cheepSaveData.shopPortalCount;
				Snapshot.RestoreEventFlags(run, cheepSaveData.eventFlags);
				foreach (RngState rng in cheepSaveData.rngs)
				{
					Snapshot.RestoreRng(run, rng);
				}
				run.SetRunStopwatch(cheepSaveData.stopwatch);
				pendingTeamExp = (ulong.TryParse(cheepSaveData.teamExp, out var result) ? result : 0);
				run.RecalculateDifficultyCoefficent();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Restoring run state failed: " + ex));
			}
			Snapshot.Current = cheepSaveData;
			announceLoaded = true;
			Plugin.Log.LogInfo((object)("Loaded " + cheepSaveData.id + ": " + cheepSaveData.sceneName + ", stage " + (cheepSaveData.stageClearCount + 1) + ", players " + cheepSaveData.players.Count));
		}

		public static void OnPlayerFirstCreated(Run run, PlayerCharacterMasterController pc)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (restoring == null || !Object.op_Implicit((Object)(object)pc) || !Object.op_Implicit((Object)(object)pc.master))
			{
				return;
			}
			NetworkUser networkUser = pc.networkUser;
			if (!Object.op_Implicit((Object)(object)networkUser))
			{
				return;
			}
			string text = Snapshot.UserKey(networkUser.id);
			if (map == null || !map.TryGetValue(text, out var value))
			{
				return;
			}
			try
			{
				CharacterMaster master = pc.master;
				Snapshot.SetBody(networkUser, value.body);
				if (Object.op_Implicit((Object)(object)master.inventory))
				{
					Snapshot.ApplyInv(master.inventory, value.inv);
				}
				master.money = value.money;
				master.voidCoins = value.voidCoins;
				value.userId = text;
				value.name = networkUser.userName;
				if (value.minions.Count > 0)
				{
					minionQueue.Add(new PendingMinions
					{
						master = master,
						list = value.minions,
						until = Time.unscaledTime + 180f
					});
				}
				Plugin.Log.LogInfo((object)("Restored " + value.name + ": " + value.body + ", items " + value.inv.items.Count + ", money " + value.money));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Restoring player " + value.name + " failed: " + ex));
			}
		}

		public static void Update()
		{
			if (Session != null && NetworkServer.active)
			{
				PreGameController instance = PreGameController.instance;
				if (Object.op_Implicit((Object)(object)instance) && !Object.op_Implicit((Object)(object)Run.instance))
				{
					if (!sessionCheckedInLobby)
					{
						sessionCheckedInLobby = true;
						if (!CheckSessionInLobby(instance))
						{
							return;
						}
					}
					if (Time.unscaledTime >= nextEnforce)
					{
						nextEnforce = Time.unscaledTime + 0.5f;
						EnforceLobby(instance);
					}
				}
			}
			if (minionQueue.Count == 0 && !announceLoaded && pendingTeamExp == 0L)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				minionQueue.Clear();
				announceLoaded = false;
				pendingTeamExp = 0uL;
				return;
			}
			if (Object.op_Implicit((Object)(object)Stage.instance))
			{
				ApplyTeamExp();
			}
			if (announceLoaded && Object.op_Implicit((Object)(object)Stage.instance))
			{
				announceLoaded = false;
				Msg(Loc.T("LOADED"));
			}
			if (!NetworkServer.active)
			{
				return;
			}
			for (int num = minionQueue.Count - 1; num >= 0; num--)
			{
				PendingMinions pendingMinions = minionQueue[num];
				if (!Object.op_Implicit((Object)(object)pendingMinions.master) || Time.unscaledTime > pendingMinions.until)
				{
					minionQueue.RemoveAt(num);
				}
				else
				{
					CharacterBody body = pendingMinions.master.GetBody();
					if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)Stage.instance))
					{
						if (pendingMinions.bodySeenAt < 0f)
						{
							pendingMinions.bodySeenAt = Time.unscaledTime;
						}
						if (!(Time.unscaledTime - pendingMinions.bodySeenAt < 2f))
						{
							foreach (MinionData item in pendingMinions.list)
							{
								Summon(body, item);
							}
							minionQueue.RemoveAt(num);
						}
					}
				}
			}
		}

		private static void Summon(CharacterBody owner, MinionData md)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0065: 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_006b: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject masterPrefab = MasterCatalog.GetMasterPrefab(MasterCatalog.FindMasterIndex(md.master));
				if (!Object.op_Implicit((Object)(object)masterPrefab))
				{
					Plugin.Log.LogWarning((object)("Unknown minion in save: " + md.master));
					return;
				}
				Vector3 val = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) * Vector3.forward * 3f;
				CharacterMaster val2 = new MasterSummon
				{
					masterPrefab = masterPrefab,
					position = owner.footPosition + val + Vector3.up * 1.5f,
					rotation = Quaternion.identity,
					summonerBodyObject = ((Component)owner).gameObject,
					ignoreTeamMemberLimit = true
				}.Perform();
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.inventory))
				{
					Snapshot.ApplyInv(val2.inventory, md.inv);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Restoring minion " + md.master + " failed: " + ex));
			}
		}
	}
	internal static class Loc
	{
		public const string Prefix = "CHEEPSAVE_";

		private static readonly string[] Langs = new string[11]
		{
			"en", "ru", "de", "es", "fr", "it", "pt", "tr", "ja", "ko",
			"zh"
		};

		private static readonly Dictionary<string, string[]> Strings = new Dictionary<string, string[]>
		{
			["SAVE"] = new string[11]
			{
				"Save game", "Сохранить игру", "Spiel speichern", "Guardar partida", "Sauvegarder la partie", "Salva partita", "Salvar jogo", "Oyunu kaydet", "ゲームをセーブ", "게임 저장",
				"保存游戏"
			},
			["SAVED_SHORT"] = new string[11]
			{
				"Game saved", "Игра сохранена", "Spiel gespeichert", "Partida guardada", "Partie sauvegardée", "Partita salvata", "Jogo salvo", "Oyun kaydedildi", "セーブしました", "저장됨",
				"已保存"
			},
			["LOAD"] = new string[11]
			{
				"Load game", "Загрузить игру", "Spiel laden", "Cargar partida", "Charger la partie", "Carica partita", "Carregar jogo", "Oyunu yükle", "ゲームをロード", "게임 불러오기",
				"读取游戏"
			},
			["LOAD_DESC"] = new string[11]
			{
				"Continue a saved run.", "Продолжить сохранённый забег.", "Einen gespeicherten Lauf fortsetzen.", "Continúa una partida guardada.", "Reprendre une partie sauvegardée.", "Continua una partita salvata.", "Continue uma partida salva.", "Kayıtlı bir oyuna devam et.", "セーブしたランを再開します。", "저장된 런을 이어서 합니다.",
				"继续已保存的游戏。"
			},
			["TAB_SOLO"] = new string[11]
			{
				"Single player", "Одиночная игра", "Einzelspieler", "Un jugador", "Solo", "Giocatore singolo", "Um jogador", "Tek oyunculu", "シングルプレイ", "싱글 플레이",
				"单人游戏"
			},
			["TAB_MULTI"] = new string[11]
			{
				"Multiplayer", "Совместная игра", "Mehrspieler", "Multijugador", "Multijoueur", "Multigiocatore", "Multijogador", "Çok oyunculu", "マルチプレイ", "멀티 플레이",
				"多人游戏"
			},
			["DELETE"] = new string[11]
			{
				"Delete", "Удалить", "Löschen", "Eliminar", "Supprimer", "Elimina", "Excluir", "Sil", "削除", "삭제",
				"删除"
			},
			["CONFIRM_DELETE"] = new string[11]
			{
				"Really delete?", "Точно удалить?", "Wirklich löschen?", "¿Eliminar de verdad?", "Vraiment supprimer ?", "Eliminare davvero?", "Excluir mesmo?", "Gerçekten silinsin mi?", "本当に削除?", "정말 삭제할까요?",
				"确定删除?"
			},
			["CLOSE"] = new string[11]
			{
				"Close", "Закрыть", "Schließen", "Cerrar", "Fermer", "Chiudi", "Fechar", "Kapat", "閉じる", "닫기",
				"关闭"
			},
			["CANCEL"] = new string[11]
			{
				"Cancel", "Отмена", "Abbrechen", "Cancelar", "Annuler", "Annulla", "Cancelar", "İptal", "キャンセル", "취소",
				"取消"
			},
			["NO_SAVES"] = new string[11]
			{
				"No saves yet. Press Esc during a run and choose \"Save game\".", "Сохранений пока нет. Нажмите Esc во время забега и выберите «Сохранить игру».", "Noch keine Spielstände. Drücke im Lauf Esc und wähle „Spiel speichern“.", "Aún no hay partidas guardadas. Pulsa Esc durante una partida y elige «Guardar partida».", "Aucune sauvegarde. Appuyez sur Échap pendant une partie et choisissez « Sauvegarder la partie ».", "Nessun salvataggio. Premi Esc durante una partita e scegli «Salva partita».", "Nenhum jogo salvo. Pressione Esc durante uma partida e escolha \"Salvar jogo\".", "Henüz kayıt yok. Oyun sırasında Esc'ye basıp \"Oyunu kaydet\"i seçin.", "セーブデータはまだありません。ラン中にEscを押して「ゲームをセーブ」を選んでください。", "저장된 게임이 없습니다. 플레이 중 Esc를 누르고 \"게임 저장\"을 선택하세요.",
				"暂无存档。游戏中按 Esc 并选择“保存游戏”。"
			},
			["STAGE_OF"] = new string[11]
			{
				"Stage {0} · {1}", "Этап {0} · {1}", "Stufe {0} · {1}", "Etapa {0} · {1}", "Niveau {0} · {1}", "Livello {0} · {1}", "Fase {0} · {1}", "Aşama {0} · {1}", "ステージ{0} · {1}", "스테이지 {0} · {1}",
				"第{0}关 · {1}"
			},
			["VERSION"] = new string[11]
			{
				"version {0}", "версия {0}", "Version {0}", "versión {0}", "version {0}", "versione {0}", "versão {0}", "sürüm {0}", "バージョン {0}", "버전 {0}",
				"版本 {0}"
			},
			["STAGE"] = new string[11]
			{
				"Stage", "Этап", "Stufe", "Etapa", "Niveau", "Livello", "Fase", "Aşama", "ステージ", "스테이지",
				"关卡"
			},
			["LOOP"] = new string[11]
			{
				"Loop {0}", "Петля {0}", "Schleife {0}", "Ciclo {0}", "Boucle {0}", "Ciclo {0}", "Ciclo {0}", "Döngü {0}", "ループ{0}", "루프 {0}",
				"第{0}轮"
			},
			["MODE"] = new string[11]
			{
				"Mode", "Режим", "Modus", "Modo", "Mode", "Modalità", "Modo", "Mod", "モード", "모드",
				"模式"
			},
			["DIFFICULTY"] = new string[11]
			{
				"Difficulty", "Сложность", "Schwierigkeit", "Dificultad", "Difficulté", "Difficoltà", "Dificuldade", "Zorluk", "難易度", "난이도",
				"难度"
			},
			["TIME"] = new string[11]
			{
				"Time", "Время", "Zeit", "Tiempo", "Temps", "Tempo", "Tempo", "Süre", "時間", "시간",
				"时间"
			},
			["LEVEL"] = new string[11]
			{
				"Team level", "Уровень команды", "Teamstufe", "Nivel del equipo", "Niveau de l'équipe", "Livello squadra", "Nível da equipe", "Takım seviyesi", "チームレベル", "팀 레벨",
				"队伍等级"
			},
			["SAVED_AT"] = new string[11]
			{
				"Saved", "Сохранено", "Gespeichert", "Guardado", "Sauvegardé", "Salvato", "Salvo em", "Kaydedildi", "セーブ日時", "저장 시각",
				"保存时间"
			},
			["PLAYERS"] = new string[11]
			{
				"Players", "Игроки", "Spieler", "Jugadores", "Joueurs", "Giocatori", "Jogadores", "Oyuncular", "プレイヤー", "플레이어",
				"玩家"
			},
			["ARTIFACTS"] = new string[11]
			{
				"Artifacts", "Артефакты", "Artefakte", "Artefactos", "Artefacts", "Artefatti", "Artefatos", "Eserler", "アーティファクト", "아티팩트",
				"神器"
			},
			["NONE"] = new string[11]
			{
				"none", "нет", "keine", "ninguno", "aucun", "nessuno", "nenhum", "yok", "なし", "없음",
				"无"
			},
			["ITEMS"] = new string[11]
			{
				"Items", "Предметы", "Gegenstände", "Objetos", "Objets", "Oggetti", "Itens", "Eşyalar", "アイテム", "아이템",
				"物品"
			},
			["EQUIPMENT"] = new string[11]
			{
				"Equipment", "Снаряжение", "Ausrüstung", "Equipamiento", "Équipement", "Equipaggiamento", "Equipamento", "Ekipman", "装備", "장비",
				"主动装备"
			},
			["ALLIES"] = new string[11]
			{
				"Allies", "Союзники", "Verbündete", "Aliados", "Alliés", "Alleati", "Aliados", "Müttefikler", "仲間", "아군",
				"盟友"
			},
			["GOLD"] = new string[11]
			{
				"Gold", "Золото", "Gold", "Oro", "Or", "Oro", "Ouro", "Altın", "ゴールド", "골드",
				"金币"
			},
			["VOID"] = new string[11]
			{
				"Void coins", "Монеты Пустоты", "Leeremünzen", "Monedas del Vacío", "Pièces du Néant", "Monete del Vuoto", "Moedas do Vazio", "Boşluk paraları", "ボイドコイン", "공허 코인",
				"虚空币"
			},
			["SELECTED"] = new string[11]
			{
				"Selected save: {0}", "Выбрано сохранение: {0}", "Gewählter Spielstand: {0}", "Partida elegida: {0}", "Sauvegarde choisie : {0}", "Salvataggio scelto: {0}", "Jogo salvo escolhido: {0}", "Seçilen kayıt: {0}", "選択したセーブ:{0}", "선택한 저장: {0}",
				"已选存档:{0}"
			},
			["HINT_LOBBY"] = new string[11]
			{
				"Survivors and rules are taken from the save. Start the run to continue.", "Персонажи и правила взяты из сохранения. Начните забег, чтобы продолжить.", "Überlebende und Regeln stammen aus dem Spielstand. Starte den Lauf, um fortzufahren.", "Los supervivientes y las reglas vienen de la partida guardada. Empieza la partida para continuar.", "Les survivants et les règles proviennent de la sauvegarde. Lancez la partie pour continuer.", "Sopravvissuti e regole provengono dal salvataggio. Avvia la partita per continuare.", "Sobreviventes e regras vêm do jogo salvo. Inicie a partida para continuar.", "Hayatta kalanlar ve kurallar kayıttan alınır. Devam etmek için oyunu başlatın.", "サバイバーとルールはセーブデータのものになります。ランを開始すると続きから遊べます。", "생존자와 규칙은 저장 파일을 따릅니다. 런을 시작하면 이어서 진행합니다.",
				"幸存者和规则取自存档。开始游戏即可继续。"
			},
			["HINT_MULTI"] = new string[11]
			{
				"Create a lobby, invite your friends and start the game – the save will be loaded.", "Создайте лобби, пригласите друзей и начните игру – сохранение загрузится.", "Erstelle eine Lobby, lade Freunde ein und starte das Spiel – der Spielstand wird geladen.", "Crea una sala, invita a tus amigos y empieza la partida: se cargará la partida guardada.", "Créez un salon, invitez vos amis et lancez la partie : la sauvegarde sera chargée.", "Crea una lobby, invita i tuoi amici e avvia la partita: il salvataggio verrà caricato.", "Crie um lobby, convide seus amigos e inicie a partida – o jogo salvo será carregado.", "Bir lobi oluşturun, arkadaşlarınızı davet edin ve oyunu başlatın – kayıt yüklenecek.", "ロビーを作成してフレンドを招待し、ゲームを開始するとセーブデータがロードされます。", "로비를 만들고 친구를 초대한 뒤 게임을 시작하면 저장 파일을 불러옵니다.",
				"创建大厅、邀请好友并开始游戏,即可读取存档。"
			},
			["CANCELLED"] = new string[11]
			{
				"Loading cancelled.", "Загрузка отменена.", "Laden abgebrochen.", "Carga cancelada.", "Chargement annulé.", "Caricamento annullato.", "Carregamento cancelado.", "Yükleme iptal edildi.", "ロードをキャンセルしました。", "불러오기를 취소했습니다.",
				"已取消读取。"
			},
			["NEED_MULTI"] = new string[11]
			{
				"This is a multiplayer save – load it from a multiplayer lobby.", "Это сохранение совместной игры – загружайте его из лобби совместной игры.", "Dies ist ein Mehrspieler-Spielstand – lade ihn aus einer Mehrspieler-Lobby.", "Es una partida multijugador: cárgala desde una sala multijugador.", "C'est une sauvegarde multijoueur : chargez-la depuis un salon multijoueur.", "È un salvataggio multigiocatore: caricalo da una lobby multigiocatore.", "Este é um jogo salvo multijogador – carregue-o em um lobby multijogador.", "Bu çok oyunculu bir kayıt – çok oyunculu bir lobiden yükleyin.", "これはマルチプレイのセーブです。マルチプレイのロビーからロードしてください。", "멀티 플레이 저장 파일입니다. 멀티 플레이 로비에서 불러오세요.",
				"这是多人存档,请在多人大厅中读取。"
			},
			["NEED_SOLO"] = new string[11]
			{
				"This is a single player save – load it from a single player game.", "Это сохранение одиночной игры – загружайте его в одиночной игре.", "Dies ist ein Einzelspieler-Spielstand – lade ihn in einem Einzelspielerspiel.", "Es una partida de un jugador: cárgala desde una partida de un jugador.", "C'est une sauvegarde solo : chargez-la depuis une partie solo.", "È un salvataggio per giocatore singolo: caricalo da una partita in singolo.", "Este é um jogo salvo de um jogador – carregue-o em uma partida de um jogador.", "Bu tek oyunculu bir kayıt – tek oyunculu bir oyundan yükleyin.", "これはシングルプレイのセーブです。シングルプレイでロードしてください。", "싱글 플레이 저장 파일입니다. 싱글 플레이에서 불러오세요.",
				"这是单人存档,请在单人游戏中读取。"
			},
			["SAVED"] = new string[11]
			{
				"Game saved: {0}. Loading restarts this stage with your current items and gold.", "Игра сохранена: {0}. При загрузке этап начнётся заново с текущими предметами и золотом.", "Spiel gespeichert: {0}. Beim Laden beginnt die Stufe neu – mit deinen aktuellen Gegenständen und deinem Gold.", "Partida guardada: {0}. Al cargarla, la etapa empieza de nuevo con tus objetos y oro actuales.", "Partie sauvegardée : {0}. Au chargement, le niveau recommence avec vos objets et votre or actuels.", "Partita salvata: {0}. Al caricamento il livello ricomincia con gli oggetti e l'oro attuali.", "Jogo salvo: {0}. Ao carregar, a fase recomeça com seus itens e ouro atuais.", "Oyun kaydedildi: {0}. Yüklendiğinde aşama mevcut eşyalarınız ve altınınızla yeniden başlar.", "セーブしました:{0}。ロードすると現在のアイテムとゴールドのままステージの最初から始まります。", "게임이 저장되었습니다: {0}. 불러오면 현재 아이템과 골드를 가진 채 스테이지를 처음부터 시작합니다.",
				"游戏已保存:{0}。读取后将保留当前物品和金币,从本关开头重新开始。"
			},
			["HOST_ONLY"] = new string[11]
			{
				"Only the host can save the game.", "Сохранять игру может только хост.", "Nur der Host kann das Spiel speichern.", "Solo el anfitrión puede guardar la partida.", "Seul l'hôte peut sauvegarder la partie.", "Solo l'host può salvare la partita.", "Apenas o anfitrião pode salvar o jogo.", "Oyunu yalnızca kurucu kaydedebilir.", "セーブできるのはホストだけです。", "호스트만 게임을 저장할 수 있습니다.",
				"只有房主可以保存游戏。"
			},
			["UNSUPPORTED"] = new string[11]
			{
				"Saving is not available in this game mode.", "В этом режиме сохранение недоступно.", "In diesem Spielmodus ist Speichern nicht möglich.", "No se puede guardar en este modo de juego.", "La sauvegarde n'est pas disponible dans ce mode de jeu.", "Il salvataggio non è disponibile in questa modalità.", "Não é possível salvar neste modo de jogo.", "Bu oyun modunda kayıt yapılamaz.", "このゲームモードではセーブできません。", "이 게임 모드에서는 저장할 수 없습니다.",
				"此游戏模式无法保存。"
			},
			["NOTHING"] = new string[11]
			{
				"Nothing to save yet – wait for the stage to load.", "Пока нечего сохранять – дождитесь загрузки этапа.", "Noch nichts zu speichern – warte, bis die Stufe geladen ist.", "Aún no hay nada que guardar: espera a que cargue la etapa.", "Rien à sauvegarder pour l'instant : attendez le chargement du niveau.", "Ancora niente da salvare: attendi il caricamento del livello.", "Ainda não há nada para salvar – aguarde a fase carregar.", "Henüz kaydedilecek bir şey yok – aşamanın yüklenmesini bekleyin.", "まだセーブできません。ステージの読み込みを待ってください。", "아직 저장할 내용이 없습니다. 스테이지가 로드될 때까지 기다리세요.",
				"暂时没有可保存的内容,请等待关卡加载。"
			},
			["WRONG_MODE"] = new string[11]
			{
				"This save is from another game mode ({0}). Choose it in the main menu.", "Это сохранение из другого режима ({0}). Выберите его в главном меню.", "Dieser Spielstand stammt aus einem anderen Spielmodus ({0}). Wähle ihn im Hauptmenü.", "Esta partida guardada es de otro modo de juego ({0}). Elígelo en el menú principal.", "Cette sauvegarde provient d'un autre mode de jeu ({0}). Choisissez-le dans le menu principal.", "Questo salvataggio appartiene a un'altra modalità ({0}). Selezionala dal menu principale.", "Este jogo salvo é de outro modo de jogo ({0}). Escolha-o no menu principal.", "Bu kayıt başka bir oyun moduna ait ({0}). Ana menüden o modu seçin.", "このセーブデータは別のゲームモード({0})のものです。メインメニューで選択してください。", "이 저장 파일은 다른 게임 모드({0})의 것입니다. 메인 메뉴에서 해당 모드를 선택하세요.",
				"此存档属于其他游戏模式({0}),请在主菜单中选择该模式。"
			},
			["LOADED"] = new string[11]
			{
				"Saved game loaded.", "Сохранение загружено.", "Spielstand geladen.", "Partida cargada.", "Sauvegarde chargée.", "Salvataggio caricato.", "Jogo salvo carregado.", "Kayıt yüklendi.", "セーブデータをロードしました。", "저장된 게임을 불러왔습니다.",
				"存档已读取。"
			},
			["ERROR"] = new string[11]
			{
				"Save error: {0}", "Ошибка сохранения: {0}", "Fehler beim Speichern: {0}", "Error de guardado: {0}", "Erreur de sauvegarde : {0}", "Errore di salvataggio: {0}", "Erro ao salvar: {0}", "Kayıt hatası: {0}", "セーブエラー:{0}", "저장 오류: {0}",
				"存档错误:{0}"
			},
			["LOAD_ERROR"] = new string[11]
			{
				"Could not load the save: {0}", "Не удалось загрузить сохранение: {0}", "Spielstand konnte nicht geladen werden: {0}", "No se pudo cargar la partida: {0}", "Impossible de charger la sauvegarde : {0}", "Impossibile caricare il salvataggio: {0}", "Não foi possível carregar o jogo salvo: {0}", "Kayıt yüklenemedi: {0}", "セーブデータをロードできませんでした:{0}", "저장 파일을 불러올 수 없습니다: {0}",
				"无法读取存档:{0}"
			},
			["DELETED_DEATH"] = new string[11]
			{
				"The run is lost – its save has been deleted.", "Забег проигран – его сохранение удалено.", "Der Lauf ist verloren – sein Spielstand wurde gelöscht.", "La partida se ha perdido: su guardado se ha eliminado.", "La partie est perdue – sa sauvegarde a été supprimée.", "La partita è persa: il suo salvataggio è stato eliminato.", "A partida foi perdida – o jogo salvo foi excluído.", "Oyun kaybedildi – kaydı silindi.", "ランに敗北しました。セーブデータを削除しました。", "런에서 패배했습니다. 저장 파일이 삭제되었습니다.",
				"本局失败,存档已删除。"
			},
			["DELETED_WIN"] = new string[11]
			{
				"The run is won – its save has been deleted.", "Забег пройден – его сохранение удалено.", "Der Lauf ist gewonnen – sein Spielstand wurde gelöscht.", "¡Partida ganada! Su guardado se ha eliminado.", "La partie est gagnée – sa sauvegarde a été supprimée.", "La partita è vinta: il suo salvataggio è stato eliminato.", "A partida foi vencida – o jogo salvo foi excluído.", "Oyun kazanıldı – kaydı silindi.", "ランに勝利しました。セーブデータを削除しました。", "런에서 승리했습니다. 저장 파일이 삭제되었습니다.",
				"本局胜利,存档已删除。"
			},
			["CANCEL_LOAD"] = new string[11]
			{
				"Cancel loading", "Отменить загрузку", "Laden abbrechen", "Cancelar carga", "Annuler le chargement", "Annulla caricamento", "Cancelar carregamento", "Yüklemeyi iptal et", "ロードをキャンセル", "불러오기 취소",
				"取消读取"
			},
			["LOBBY_PICK"] = new string[11]
			{
				"picked in lobby: {0}", "в лобби: {0}", "in der Lobby: {0}", "en la sala: {0}", "dans le salon : {0}", "nella lobby: {0}", "no lobby: {0}", "lobide: {0}", "ロビーで選択:{0}", "로비 선택: {0}",
				"大厅选择:{0}"
			},
			["SETTINGS"] = new string[11]
			{
				"Settings", "Настройки", "Einstellungen", "Ajustes", "Paramètres", "Impostazioni", "Configurações", "Ayarlar", "設定", "설정",
				"设置"
			},
			["SETTINGS_NOTE"] = new string[11]
			{
				"Changes apply right away and are stored in BepInEx/config/user.cheepsave.cfg. Only the host's settings matter.", "Изменения действуют сразу и хранятся в BepInEx/config/user.cheepsave.cfg. Важны настройки хоста.", "Änderungen gelten sofort und werden in BepInEx/config/user.cheepsave.cfg gespeichert. Es zählen die Einstellungen des Hosts.", "Los cambios se aplican al momento y se guardan en BepInEx/config/user.cheepsave.cfg. Cuentan los ajustes del anfitrión.", "Les changements s'appliquent tout de suite et sont enregistrés dans BepInEx/config/user.cheepsave.cfg. Seuls ceux de l'hôte comptent.", "Le modifiche valgono subito e sono salvate in BepInEx/config/user.cheepsave.cfg. Contano le impostazioni dell'host.", "As mudanças valem na hora e ficam em BepInEx/config/user.cheepsave.cfg. Valem as configurações do anfitrião.", "Değişiklikler hemen geçerli olur ve BepInEx/config/user.cheepsave.cfg dosyasına kaydedilir. Kurucunun ayarları geçerlidir.", "変更はすぐに反映され、BepInEx/config/user.cheepsave.cfg に保存されます。ホストの設定が使われます。", "변경 사항은 즉시 적용되며 BepInEx/config/user.cheepsave.cfg에 저장됩니다. 호스트의 설정이 적용됩니다.",
				"更改立即生效并保存在 BepInEx/config/user.cheepsave.cfg 中。以房主的设置为准。"
			},
			["OPT_AUTOSAVE"] = new string[11]
			{
				"Auto save", "Автосохранение", "Automatisch speichern", "Guardado automático", "Sauvegarde automatique", "Salvataggio automatico", "Salvamento automático", "Otomatik kayıt", "オートセーブ", "자동 저장",
				"自动存档"
			},
			["OPT_AUTOSAVE_DESC"] = new string[11]
			{
				"Also write the save automatically at the start of every stage.", "Записывать сохранение автоматически в начале каждого этапа.", "Den Spielstand zusätzlich zu Beginn jeder Stufe automatisch schreiben.", "Guardar también automáticamente al comienzo de cada etapa.", "Écrire aussi la sauvegarde automatiquement au début de chaque niveau.", "Salva anche automaticamente all'inizio di ogni livello.", "Também salvar automaticamente no início de cada fase.", "Her aşamanın başında kaydı otomatik olarak da yaz.", "各ステージの開始時にも自動でセーブします。", "각 스테이지가 시작될 때도 자동으로 저장합니다.",
				"每关开始时也自动存档。"
			},
			["OPT_STAGESTART"] = new string[11]
			{
				"Save as at stage start", "Сохранять как в начале этапа", "Stand vom Stufenbeginn speichern", "Guardar como al inicio de la etapa", "Sauvegarder l'état du début du niveau", "Salva come a inizio livello", "Salvar como no início da fase", "Aşama başındaki hâli kaydet", "ステージ開始時の状態でセーブ", "스테이지 시작 시점으로 저장",
				"按关卡开始时的状态存档"
			},
			["OPT_STAGESTART_DESC"] = new string[11]
			{
				"Items, gold and allies are saved as they were at the start of the stage, not at the moment of saving.", "Предметы, золото и союзники сохраняются такими, какими были в начале этапа, а не в момент сохранения.", "Gegenstände, Gold und Verbündete werden wie zu Beginn der Stufe gespeichert, nicht wie beim Speichern.", "Objetos, oro y aliados se guardan como estaban al inicio de la etapa, no en el momento de guardar.", "Objets, or et alliés sont sauvegardés tels qu'au début du niveau, et non au moment de la sauvegarde.", "Oggetti, oro e alleati vengono salvati com'erano a inizio livello, non al momento del salvataggio.", "Itens, ouro e aliados são salvos como estavam no início da fase, não no momento de salvar.", "Eşyalar, altın ve müttefikler kayıt anındaki gibi değil, aşamanın başındaki gibi kaydedilir.", "アイテム・ゴールド・味方は、セーブした時点ではなくステージ開始時の状態で保存されます。", "아이템, 골드, 아군을 저장 시점이 아니라 스테이지 시작 시점 상태로 저장합니다.",
				"物品、金钱和盟友按关卡开始时的状态保存,而不是存档那一刻。"
			},
			["OPT_DELDEATH"] = new string[11]
			{
				"Delete save on death", "Удалять сохранение при смерти", "Spielstand bei Tod löschen", "Eliminar guardado al morir", "Supprimer la sauvegarde à la mort", "Elimina salvataggio alla morte", "Excluir jogo salvo ao morrer", "Ölünce kaydı sil", "死亡時にセーブを削除", "사망 시 저장 삭제",
				"死亡时删除存档"
			},
			["OPT_DELDEATH_DESC"] = new string[11]
			{
				"When the run is lost (the whole team died), its save is deleted.", "Если забег проигран (погибла вся команда), его сохранение удаляется.", "Ist der Lauf verloren (das ganze Team ist tot), wird sein Spielstand gelöscht.", "Si la partida se pierde (murió todo el equipo), se elimina su guardado.", "Si la partie est perdue (toute l'équipe est morte), sa sauvegarde est supprimée.", "Se la partita è persa (è morta tutta la squadra), il suo salvataggio viene eliminato.", "Se a partida for perdida (a equipe toda morreu), o jogo salvo é excluído.", "Oyun kaybedilirse (tüm takım öldüyse) kaydı silinir.", "ランに敗北すると(チーム全員が死亡)、そのセーブデータを削除します。", "런에서 패배하면(팀 전원 사망) 해당 저장 파일을 삭제합니다.",
				"本局失败(全队阵亡)时删除其存档。"
			},
			["OPT_DELWIN"] = new string[11]
			{
				"Delete save on victory", "Удалять сохранение при победе", "Spielstand bei Sieg löschen", "Eliminar guardado al ganar", "Supprimer la sauvegarde en cas de victoire", "Elimina salvataggio alla vittoria", "Excluir jogo salvo ao vencer", "Kazanınca kaydı sil", "勝利時にセーブを削除", "승리 시 저장 삭제",
				"胜利时删除存档"
			},
			["OPT_DELWIN_DESC"] = new string[11]
			{
				"When the run is won, its save is deleted.", "Если забег пройден, его сохранение удаляется.", "Ist der Lauf gewonnen, wird sein Spielstand gelöscht.", "Si la partida se gana, se elimina su guardado.", "Si la partie est gagnée, sa sauvegarde est supprimée.", "Se la partita è vinta, il suo salvataggio viene eliminato.", "Se a partida for vencida, o jogo salvo é excluído.", "Oyun kazanılırsa kaydı silinir.", "ランに勝利すると、そのセーブデータを削除します。", "런에서 승리하면 해당 저장 파일을 삭제합니다.",
				"本局胜利时删除其存档。"
			}
		};

		private static int LangIndex(string languageName)
		{
			if (string.IsNullOrEmpty(languageName))
			{
				return 0;
			}
			string text = languageName.ToLowerInvariant();
			for (int i = 0; i < Langs.Length; i++)
			{
				if (text == Langs[i] || text.StartsWith(Langs[i] + "-"))
				{
					return i;
				}
			}
			return 0;
		}

		public static string Get(string key, string languageName)
		{
			if (!Strings.TryGetValue(key, out var value))
			{
				return "CHEEPSAVE_" + key;
			}
			return value[LangIndex(languageName)];
		}

		public static string T(string key)
		{
			return Get(key, Language.currentLanguageName);
		}
	}
	internal static class Pad
	{
		private static readonly FieldInfo glyphMapField = AccessTools.Field(typeof(Glyphs), "glyphMap");

		private static int heldDir;

		private static float nextRepeat;

		private static readonly List<HGGamepadInputEvent> muted = new List<HGGamepadInputEvent>();

		private static bool blocked;

		private static int releaseFrame = -1;

		private static MPEventSystem Es => MPEventSystemManager.primaryEventSystem;

		public static bool Active
		{
			get
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Invalid comparison between Unknown and I4
				MPEventSystem es = Es;
				if (Object.op_Implicit((Object)(object)es))
				{
					return (int)es.currentInputSource == 1;
				}
				return false;
			}
		}

		public static bool Down(string action)
		{
			MPEventSystem es = Es;
			if (Object.op_Implicit((Object)(object)es) && es.player != null)
			{
				return es.player.GetButtonDown(action);
			}
			return false;
		}

		public static float Axis(string action)
		{
			MPEventSystem es = Es;
			if (!Object.op_Implicit((Object)(object)es) || es.player == null)
			{
				return 0f;
			}
			return es.player.GetAxis(action);
		}

		public static string Glyph(string action)
		{
			if (!Active)
			{
				return "";
			}
			return GamepadGlyph(action);
		}

		public static string GamepadGlyph(string action)
		{
			MPEventSystem es = Es;
			if (!Object.op_Implicit((Object)(object)es) || es.player == null)
			{
				return "";
			}
			try
			{
				string glyphString = Glyphs.GetGlyphString(es, action, (AxisRange)0, (InputSource)1, false);
				if (string.IsNullOrEmpty(glyphString) || glyphString.StartsWith("[", StringComparison.Ordinal) || glyphString == Language.GetString("INPUT_GAMEPAD_UNBOUND"))
				{
					return "";
				}
				return glyphString;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Glyph " + action + ": " + ex.Message));
				return "";
			}
		}

		private static IControllerTemplateButton TopButton(Joystick j)
		{
			try
			{
				object result;
				if (j == null)
				{
					result = null;
				}
				else
				{
					IGamepadTemplate template = ((Controller)j).GetTemplate<IGamepadTemplate>();
					result = ((template != null) ? template.actionTopRow2 : null);
				}
				return (IControllerTemplateButton)result;
			}
			catch
			{
				return null;
			}
		}

		public static bool YDown()
		{
			MPEventSystem es = Es;
			if (!Object.op_Implicit((Object)(object)es) || es.player == null)
			{
				return false;
			}
			foreach (Joystick joystick in es.player.controllers.Joysticks)
			{
				IControllerTemplateButton val = TopButton(joystick);
				if (val != null && val.justPressed)
				{
					return true;
				}
			}
			return false;
		}

		public static string YGlyph()
		{
			if (!Active)
			{
				return "";
			}
			MPEventSystem es = Es;
			Controller lastActiveController = es.player.controllers.GetLastActiveController((ControllerType)2);
			Joystick val = (Joystick)(object)((lastActiveController is Joystick) ? lastActiveController : null);
			if (val == null && es.player.controllers.joystickCount > 0)
			{
				val = es.player.controllers.Joysticks[0];
			}
			if (val == null)
			{
				return "";
			}
			IControllerTemplateButton obj = TopButton(val);
			IControllerTemplateButtonSource val2 = ((obj != null) ? obj.source : null);
			if (val2 != null && val2.target.hasTarget)
			{
				string text = GlyphFor(((Controller)val).name, val2.target.elementIdentifierId);
				if (text != null)
				{
					return text;
				}
			}
			return "<b>Y</b>";
		}

		private static string GlyphFor(string device, int elementId)
		{
			if (!(glyphMapField?.GetValue(null) is IDictionary dictionary))
			{
				return null;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				Type type = item.Key.GetType();
				if ((string)type.GetField("deviceName").GetValue(item.Key) == device && (int)type.GetField("elementId").GetValue(item.Key) == elementId)
				{
					return item.Value as string;
				}
			}
			return null;
		}

		public static int Step()
		{
			float num = Axis("UIVertical");
			int num2 = ((num > 0.5f) ? 1 : ((num < -0.5f) ? (-1) : 0));
			if (num2 == 0)
			{
				heldDir = 0;
				return 0;
			}
			float unscaledTime = Time.unscaledTime;
			if (num2 != heldDir)
			{
				heldDir = num2;
				nextRepeat = unscaledTime + 0.4f;
				return num2;
			}
			if (unscaledTime < nextRepeat)
			{
				return 0;
			}
			nextRepeat = unscaledTime + 0.11f;
			return num2;
		}

		public static void Block()
		{
			releaseFrame = -1;
			if (blocked)
			{
				return;
			}
			blocked = true;
			MPButton.BlockMPButton();
			HGGamepadInputEvent[] array = Object.FindObjectsOfType<HGGamepadInputEvent>();
			foreach (HGGamepadInputEvent val in array)
			{
				if (((Behaviour)val).enabled)
				{
					((Behaviour)val).enabled = false;
					muted.Add(val);
				}
			}
		}

		public static void Release()
		{
			if (blocked)
			{
				releaseFrame = Time.frameCount + 1;
			}
		}

		public static void Update()
		{
			if (!blocked)
			{
				return;
			}
			if (releaseFrame >= 0 && Time.frameCount >= releaseFrame)
			{
				blocked = false;
				releaseFrame = -1;
				MPButton.UnblockMPButton();
				foreach (HGGamepadInputEvent item in muted)
				{
					if (Object.op_Implicit((Object)(object)item))
					{
						((Behaviour)item).enabled = true;
					}
				}
				muted.Clear();
				return;
			}
			foreach (MPEventSystem readOnlyInstances in MPEventSystem.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)((EventSystem)readOnlyInstances).currentSelectedGameObject))
				{
					((EventSystem)readOnlyInstances).SetSelectedGameObject((GameObject)null);
				}
			}
		}
	}
	internal static class Panel
	{
		public enum Context
		{
			MainMenu,
			Lobby
		}

		private class Option
		{
			public ConfigEntry<bool> entry;

			public string key;
		}

		private class Item
		{
			public Sprite icon;

			public Texture bg;

			public string name;

			public int count;
		}

		private class Ally
		{
			public Texture icon;

			public string name;

			public int count;
		}

		private static Context context;

		private static bool multiplayerTab;

		private static List<SaveEntry> entries = new List<SaveEntry>();

		private static int selected;

		private static bool confirmDelete;

		private static Canvas canvas;

		private static RectTransform root;

		private static RectTransform listContent;

		private static RectTransform detailContent;

		private static RectTransform tip;

		private static TextMeshProUGUI tipText;

		private static TextMeshProUGUI deleteLabel;

		private static TextMeshProUGUI loadLabel;

		private static TextMeshProUGUI closeLabel;

		private static TextMeshProUGUI soloTabLabel;

		private static TextMeshProUGUI multiTabLabel;

		private static TextMeshProUGUI gearGlyph;

		private static Button loadBtn;

		private static Button deleteBtn;

		private static readonly List<Image> cardBgs = new List<Image>();

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

		private static float listW;

		private static float detailW;

		private static int openedFrame;

		private static bool padLabels;

		private const float CardH = 148f;

		private const float CardGap = 12f;

		private const string PadDelete = "UISubmitAlt";

		private const float Tile = 60f;

		private const float TileGap = 8f;

		private static RectTransform settings;

		private static int settingsSel;

		public static bool IsOpen => Object.op_Implicit((Object)(object)canvas);

		public static int ClosedFrame { get; private set; } = -1;

		public static void Open(Context ctx)
		{
			Close();
			context = ctx;
			openedFrame = Time.frameCount;
			Pad.Block();
			if (ctx == Context.Lobby)
			{
				multiplayerTab = !RoR2Application.isInSinglePlayer;
			}
			try
			{
				Build();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Load window failed: " + ex));
				Close();
			}
		}

		public static void Close()
		{
			if (Object.op_Implicit((Object)(object)canvas))
			{
				Object.Destroy((Object)(object)((Component)canvas).gameObject);
			}
			if (Object.op_Implicit((Object)(object)canvas))
			{
				ClosedFrame = Time.frameCount;
			}
			canvas = null;
			tip = null;
			settings = null;
			Pad.Release();
		}

		public static void Update()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)canvas))
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				if (Object.op_Implicit((Object)(object)settings))
				{
					CloseSettings();
				}
				else
				{
					Close();
				}
			}
			else if (context == Context.Lobby && !Object.op_Implicit((Object)(object)PreGameController.instance))
			{
				Close();
			}
			else if (context == Context.MainMenu && !Object.op_Implicit((Object)(object)MainMenuController.instance))
			{
				Close();
			}
			else if (Time.frameCount == openedFrame || !(Object.op_Implicit((Object)(object)settings) ? HandleSettingsPad() : HandlePad()))
			{
				if (Pad.Active != padLabels)
				{
					RefreshLabels();
				}
				if (Object.op_Implicit((Object)(object)tip) && ((Component)tip).gameObject.activeSelf)
				{
					Vector2 val = default(Vector2);
					RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)canvas).transform, Vector2.op_Implicit(Input.mousePosition), (Camera)null, ref val);
					float x = tip.sizeDelta.x;
					float width = CursorFix.Width;
					float num = Mathf.Min(val.x + 18f, width / 2f - x - 8f);
					tip.anchoredPosition = new Vector2(num, val.y - 22f);
				}
			}
		}

		public static void ShowTip(string text)
		{
			//IL_003c: 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)
			if (Object.op_Implicit((Object)(object)tip))
			{
				if (string.IsNullOrEmpty(text))
				{
					((Component)tip).gameObject.SetActive(false);
					return;
				}
				((TMP_Text)tipText).text = text;
				tip.sizeDelta = new Vector2(((TMP_Text)tipText).GetPreferredValues(text).x + 28f, 40f);
				((Component)tip).gameObject.SetActive(true);
				((Transform)tip).SetAsLastSibling();
			}
		}

		private static void Build()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00b4: 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_00bd: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_0675: Unknown result type (might be due to invalid IL or missing references)
			//IL_070d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0712: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e0: Expected O, but got Unknown
			//IL_0805: Unknown result type (might be due to invalid IL or missing references)
			//IL_080c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0822: Unknown result type (might be due to invalid IL or missing references)
			//IL_083b: Unknown result type (might be due to invalid IL or missing references)
			canvas = CursorFix.MakeCanvas("CheepSaveWindow", 32000);
			RectTransform val = (RectTransform)((Component)canvas).transform;
			((Graphic)Kit.Img((Transform)val, new Color(0f, 0f, 0f, 0.72f), null, raycast: true, "Dim")).rectTransform.Fill();
			float num = Mathf.Min(1720f, CursorFix.Width - 80f);
			float num2 = 960f;
			root = Kit.Node((Transform)val, "Window");
			RectTransform obj = root;
			RectTransform obj2 = root;
			RectTransform obj3 = root;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			obj3.pivot = val2;
			Vector2 val3 = (obj.anchorMin = (obj2.anchorMax = val2));
			root.sizeDelta = new Vector2(num, num2);
			((Graphic)Kit.Img((Transform)(object)root, Kit.Surface, Kit.Round, raycast: true, "Bg")).rectTransform.Fill();
			((Graphic)Kit.Img((Transform)(object)root, Kit.Stroke, Kit.Ring, raycast: false, "Stroke")).rectTransform.Fill();
			((Graphic)Kit.Img((Transform)(object)root, Kit.Teal, Kit.RoundSmall, raycast: false, "Accent")).rectTransform.At(32f, 0f, 120f, 4f);
			((Graphic)Kit.Raw((Transform)(object)root, Kit.Tex("RoR2/Base/Common/MiscIcons/texRoR2Icon.png"), Kit.Teal)).rectTransform.At(32f, 30f, 44f, 44f);
			((TMP_Text)Kit.Txt((Transform)(object)root, Loc.T("LOAD"), 38f, Kit.Text, (TextAlignmentOptions)4097, bold: true)).rectTransform.At(90f, 22f, 600f, 60f);
			float num3 = 260f;
			float num4 = num - 32f - num3 * 2f - 8f;
			((Graphic)Kit.Img((Transform)(object)root, Kit.Card, Kit.Round, raycast: false, "Tabs")).rectTransform.At(num4 - 6f, 22f, num3 * 2f + 20f, 60f);
			soloTabLabel = Tab(root, num4, multi: false, num3);
			multiTabLabel = Tab(root, num4 + num3 + 8f, multi: true, num3);
			float num5 = num4 - 6f - 16f - 60f;
			Button obj4 = Kit.Btn((Transform)(object)root, null, Kit.Card, Kit.Text, OpenSettings);
			((Component)obj4).GetComponent<RectTransform>().At(num5, 22f, 60f, 60f);
			((Graphic)Kit.Img(((Component)obj4).transform, Kit.Text, Kit.Gear, raycast: false, "Gear")).rectTransform.At(14f, 14f, 32f, 32f);
			Kit.Tip((Graphic)(object)((Component)obj4).GetComponent<Image>(), Loc.T("SETTINGS"));
			gearGlyph = Kit.Txt((Transform)(object)root, "", 26f, Kit.Text, (TextAlignmentOptions)4100);
			((TMP_Text)gearGlyph).rectTransform.At(num5 - 70f, 22f, 62f, 60f);
			((Graphic)Kit.Img((Transform)(object)root, Kit.Stroke, null, raycast: false, "Line")).rectTransform.At(32f, 102f, num - 64f, 1f);
			entries = SaveStore.List(multiplayerTab);
			selected = 0;
			confirmDelete = false;
			float num6 = 124f;
			float num7 = 112f;
			float num8 = num2 - num6 - num7;
			listW = 560f;
			detailW = num - 64f - listW - 28f;
			if (entries.Count == 0)
			{
				RectTransform parent = Kit.Node((Transform)(object)root, "Empty").At(32f, num6, num - 64f, num8);
				((Graphic)Kit.Raw((Transform)(object)parent, Kit.Tex("RoR2/Base/Common/MiscIcons/texMysteryIcon.png"), (Color?)new Color(1f, 1f, 1f, 0.35f))).rectTransform.At((num - 64f) / 2f - 48f, num8 / 2f - 130f, 96f, 96f);
				((TMP_Text)Kit.Txt((Transform)(object)parent, Loc.T("NO_SAVES"), 26f, Kit.Muted, (TextAlignmentOptions)258, bold: false, wrap: true)).rectTransform.At(80f, num8 / 2f - 10f, num - 64f - 160f, 120f);
			}
			else
			{
				listContent = Scroll(root, 32f, num6, listW, num8, "List");
				detailContent = Scroll(root, 32f + listW + 28f, num6, detailW, num8, "Details");
				BuildList();
				BuildDetails();
			}
			float y = num2 - 88f;
			((TMP_Text)Kit.Txt((Transform)(object)root, "<b>CheepSave</b>   " + string.Format(Loc.T("VERSION"), "1.0.2"), 17f, new Color(1f, 1f, 1f, 0.3f), (TextAlignmentOptions)1025)).rectTransform.At(36f, y, 500f, 56f);
			loadBtn = Kit.Btn((Transform)(object)root, Loc.T("LOAD"), Kit.Teal, Color32.op_Implicit(new Color32((byte)6, (byte)24, (byte)22, byte.MaxValue)), LoadSelected, 26f);
			((Component)loadBtn).GetComponent<RectTransform>().At(num - 32f - 320f, y, 320f, 62f);
			loadLabel = ((Component)loadBtn).GetComponentInChildren<TextMeshProUGUI>();
			Button obj5 = Kit.Btn((Transform)(object)root, Loc.T("CLOSE"), Kit.Card, Kit.Text, Close);
			((Component)obj5).GetComponent<RectTransform>().At(num - 32f - 320f - 16f - 220f, y, 220f, 62f);
			closeLabel = ((Component)obj5).GetComponentInChildren<TextMeshProUGUI>();
			deleteBtn = Kit.Btn((Transform)(object)root, Loc.T("DELETE"), new Color(Kit.Danger.r, Kit.Danger.g, Kit.Danger.b, 0.22f), Kit.Danger, DeleteSelected);
			((Component)deleteBtn).GetComponent<RectTransform>().At(num - 32f - 320f - 16f - 220f - 16f - 260f, y, 260f, 62f);
			deleteLabel = ((Component)deleteBtn).GetComponentInChildren<TextMeshProUGUI>();
			Button obj6 = loadBtn;
			bool interactable = (((Selectable)deleteBtn).interactable = entries.Count > 0);
			((Selectable)obj6).interactable = interactable;
			RefreshLabels();
			tip = ((Graphic)Kit.Img((Transform)val, Color32.op_Implicit(new Color32((byte)4, (byte)6, (byte)9, (byte)245)), Kit.RoundSmall, raycast: false, "Tip")).rectTransform;
			RectTransform obj7 = tip;
			RectTransform obj8 = tip;
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			obj8.anchorMax = val3;
			obj7.anchorMin = val3;
			tip.pivot = new Vector2(0f, 1f);
			tipText = Kit.Txt((Transform)(object)tip, "", 19f, Kit.Text, (TextAlignmentOptions)4097);
			((TMP_Text)tipText).rectTransform.Fill(14f, 0f, 10f);
			((Component)tip).gameObject.SetActive(false);
		}

		private static TextMeshProUGUI Tab(RectTransform parent, float x, bool multi, float w)
		{
			//IL_0053: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			bool flag = multiplayerTab == multi;
			Button obj = Kit.Btn((Transform)(object)parent, Loc.T(multi ? "TAB_MULTI" : "TAB_SOLO"), (Color)(flag ? Kit.Teal : new Color(0f, 0f, 0f, 0f)), flag ? Color32.op_Implicit(new Color32((byte)6, (byte)24, (byte)22, byte.MaxValue)) : Kit.Muted, delegate
			{
				SwitchTab(multi);
			}, 21f);
			((Component)obj).GetComponent<RectTransform>().At(x, 28f, w, 48f);
			((Selectable)obj).interactable = flag || context == Context.MainMenu;
			return ((Component)obj).GetComponentInChildren<TextMeshProUGUI>();
		}

		private static void SwitchTab(bool multi)
		{
			if (multiplayerTab != multi && context == Context.MainMenu)
			{
				multiplayerTab = multi;
				Open(context);
			}
		}

		private static RectTransform Scroll(RectTransform parent, float x, float y, float w, float h, string name)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: