plugins/CENI/CENI.dll

Decompiled 9 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.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BiggerBazaar;
using HG;
using HG.Reflection;
using IL.RoR2;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour.HookGen;
using On.RoR2;
using On.RoR2.UI;
using PSTinyJson;
using ProperSave.Components;
using ProperSave.Data;
using ProperSave.Old;
using ProperSave.Old.Data;
using ProperSave.Old.SaveData;
using ProperSave.Old.SaveData.Artifacts;
using ProperSave.Old.SaveData.Runs;
using ProperSave.SaveData;
using ProperSave.SaveData.Artifacts;
using ProperSave.SaveData.Runs;
using ProperSave.TinyJson;
using ProperSave.Utils;
using R2API;
using RoR2;
using RoR2.Artifacts;
using RoR2.CharacterAI;
using RoR2.ContentManagement;
using RoR2.ExpansionManagement;
using RoR2.Networking;
using RoR2.Skills;
using RoR2.Stats;
using RoR2.UI;
using ShareSuite;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zio;
using Zio.FileSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PSTinyJson
{
	public static class JSONParser
	{
		[ThreadStatic]
		private static Stack<List<string>> splitArrayPool;

		[ThreadStatic]
		private static StringBuilder stringBuilder;

		[ThreadStatic]
		private static Dictionary<Type, Dictionary<string, FieldInfo>> fieldInfoCache;

		[ThreadStatic]
		private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyInfoCache;

		public static T FromJson<T>(this string json)
		{
			return (T)json.FromJson(typeof(T));
		}

		public static object FromJson(this string json, Type type)
		{
			if (propertyInfoCache == null)
			{
				propertyInfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
			}
			if (fieldInfoCache == null)
			{
				fieldInfoCache = new Dictionary<Type, Dictionary<string, FieldInfo>>();
			}
			if (stringBuilder == null)
			{
				stringBuilder = new StringBuilder();
			}
			if (splitArrayPool == null)
			{
				splitArrayPool = new Stack<List<string>>();
			}
			stringBuilder.Length = 0;
			for (int i = 0; i < json.Length; i++)
			{
				char c = json[i];
				if (c == '"')
				{
					i = AppendUntilStringEnd(appendEscapeCharacter: true, i, json);
				}
				else if (!char.IsWhiteSpace(c))
				{
					stringBuilder.Append(c);
				}
			}
			return ParseValue(type, stringBuilder.ToString());
		}

		private static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
		{
			stringBuilder.Append(json[startIdx]);
			for (int i = startIdx + 1; i < json.Length; i++)
			{
				if (json[i] == '\\')
				{
					if (appendEscapeCharacter)
					{
						stringBuilder.Append(json[i]);
					}
					stringBuilder.Append(json[i + 1]);
					i++;
				}
				else
				{
					if (json[i] == '"')
					{
						stringBuilder.Append(json[i]);
						return i;
					}
					stringBuilder.Append(json[i]);
				}
			}
			return json.Length - 1;
		}

		private static List<string> Split(string json)
		{
			List<string> list = ((splitArrayPool.Count > 0) ? splitArrayPool.Pop() : new List<string>());
			list.Clear();
			if (json.Length == 2)
			{
				return list;
			}
			int num = 0;
			stringBuilder.Length = 0;
			for (int i = 1; i < json.Length - 1; i++)
			{
				switch (json[i])
				{
				case '[':
				case '{':
					num++;
					break;
				case ']':
				case '}':
					num--;
					break;
				case '"':
					i = AppendUntilStringEnd(appendEscapeCharacter: true, i, json);
					continue;
				case ',':
				case ':':
					if (num == 0)
					{
						list.Add(stringBuilder.ToString());
						stringBuilder.Length = 0;
						continue;
					}
					break;
				}
				stringBuilder.Append(json[i]);
			}
			list.Add(stringBuilder.ToString());
			return list;
		}

		internal static object ParseValue(Type type, string json)
		{
			if (type == typeof(string))
			{
				if (json.Length <= 2)
				{
					return string.Empty;
				}
				StringBuilder stringBuilder = new StringBuilder(json.Length);
				for (int i = 1; i < json.Length - 1; i++)
				{
					if (json[i] == '\\' && i + 1 < json.Length - 1)
					{
						int num = "\"\\nrtbf/".IndexOf(json[i + 1]);
						if (num >= 0)
						{
							stringBuilder.Append("\"\\\n\r\t\b\f/"[num]);
							i++;
							continue;
						}
						if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
						{
							uint result = 0u;
							if (uint.TryParse(json.Substring(i + 2, 4), NumberStyles.AllowHexSpecifier, null, out result))
							{
								stringBuilder.Append((char)result);
								i += 5;
								continue;
							}
						}
					}
					stringBuilder.Append(json[i]);
				}
				return stringBuilder.ToString();
			}
			if (type.IsPrimitive)
			{
				return Convert.ChangeType(json, type, CultureInfo.InvariantCulture);
			}
			if (type == typeof(decimal))
			{
				decimal.TryParse(json, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2);
				return result2;
			}
			if (json == "null")
			{
				return null;
			}
			if (type.IsEnum)
			{
				if (json[0] == '"')
				{
					json = json.Substring(1, json.Length - 2);
					try
					{
						return Enum.Parse(type, json, ignoreCase: false);
					}
					catch
					{
						return 0;
					}
				}
				return Convert.ChangeType(json, Enum.GetUnderlyingType(type));
			}
			if (type.IsArray)
			{
				Type elementType = type.GetElementType();
				if (json[0] != '[' || json[json.Length - 1] != ']')
				{
					return null;
				}
				List<string> list = Split(json);
				Array array = Array.CreateInstance(elementType, list.Count);
				for (int j = 0; j < list.Count; j++)
				{
					array.SetValue(ParseValue(elementType, list[j]), j);
				}
				splitArrayPool.Push(list);
				return array;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
			{
				Type type2 = type.GetGenericArguments()[0];
				if (json[0] != '[' || json[json.Length - 1] != ']')
				{
					return null;
				}
				List<string> list2 = Split(json);
				IList list3 = (IList)type.GetConstructor(new Type[1] { typeof(int) }).Invoke(new object[1] { list2.Count });
				for (int k = 0; k < list2.Count; k++)
				{
					list3.Add(ParseValue(type2, list2[k]));
				}
				splitArrayPool.Push(list2);
				return list3;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				Type[] genericArguments = type.GetGenericArguments();
				Type type3 = genericArguments[0];
				Type type4 = genericArguments[1];
				if (type3 != typeof(string))
				{
					return null;
				}
				if (json[0] != '{' || json[json.Length - 1] != '}')
				{
					return null;
				}
				List<string> list4 = Split(json);
				if (list4.Count % 2 != 0)
				{
					return null;
				}
				IDictionary dictionary = (IDictionary)type.GetConstructor(new Type[1] { typeof(int) }).Invoke(new object[1] { list4.Count / 2 });
				for (int l = 0; l < list4.Count; l += 2)
				{
					if (list4[l].Length > 2)
					{
						string key = list4[l].Substring(1, list4[l].Length - 2);
						object value = ParseValue(type4, list4[l + 1]);
						dictionary.Add(key, value);
					}
				}
				return dictionary;
			}
			if (type == typeof(object))
			{
				return ParseAnonymousValue(json);
			}
			if (json[0] == '{' && json[json.Length - 1] == '}')
			{
				return ParseObject(type, json);
			}
			return null;
		}

		private static object ParseAnonymousValue(string json)
		{
			if (json.Length == 0)
			{
				return null;
			}
			if (json[0] == '{' && json[json.Length - 1] == '}')
			{
				List<string> list = Split(json);
				if (list.Count % 2 != 0)
				{
					return null;
				}
				Dictionary<string, object> dictionary = new Dictionary<string, object>(list.Count / 2);
				for (int i = 0; i < list.Count; i += 2)
				{
					dictionary.Add(list[i].Substring(1, list[i].Length - 2), ParseAnonymousValue(list[i + 1]));
				}
				return dictionary;
			}
			if (json[0] == '[' && json[json.Length - 1] == ']')
			{
				List<string> list2 = Split(json);
				List<object> list3 = new List<object>(list2.Count);
				for (int j = 0; j < list2.Count; j++)
				{
					list3.Add(ParseAnonymousValue(list2[j]));
				}
				return list3;
			}
			if (json[0] == '"' && json[json.Length - 1] == '"')
			{
				return json.Substring(1, json.Length - 2).Replace("\\", string.Empty);
			}
			if (char.IsDigit(json[0]) || json[0] == '-')
			{
				if (json.Contains("."))
				{
					double.TryParse(json, NumberStyles.Float, CultureInfo.InvariantCulture, out var result);
					return result;
				}
				int.TryParse(json, out var result2);
				return result2;
			}
			if (json == "true")
			{
				return true;
			}
			if (json == "false")
			{
				return false;
			}
			return null;
		}

		private static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members) where T : MemberInfo
		{
			Dictionary<string, T> dictionary = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
			foreach (T val in members)
			{
				if (val.IsDefined(typeof(IgnoreDataMemberAttribute), inherit: true))
				{
					continue;
				}
				string name = val.Name;
				if (val.IsDefined(typeof(DataMemberAttribute), inherit: true))
				{
					DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(val, typeof(DataMemberAttribute), inherit: true);
					if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
					{
						name = dataMemberAttribute.Name;
					}
				}
				dictionary.Add(name, val);
			}
			return dictionary;
		}

		private static object ParseObject(Type type, string json)
		{
			object uninitializedObject = FormatterServices.GetUninitializedObject(type);
			List<string> list = Split(json);
			if (list.Count % 2 != 0)
			{
				return uninitializedObject;
			}
			if (!fieldInfoCache.TryGetValue(type, out var value))
			{
				value = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
				fieldInfoCache.Add(type, value);
			}
			if (!propertyInfoCache.TryGetValue(type, out var value2))
			{
				value2 = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
				propertyInfoCache.Add(type, value2);
			}
			for (int i = 0; i < list.Count; i += 2)
			{
				if (list[i].Length > 2)
				{
					string key = list[i].Substring(1, list[i].Length - 2);
					string json2 = list[i + 1];
					PropertyInfo value4;
					if (value.TryGetValue(key, out var value3))
					{
						DiscoverObjectTypeAttribute customAttribute = value3.GetCustomAttribute<DiscoverObjectTypeAttribute>();
						value3.SetValue(uninitializedObject, ParseValue(customAttribute?.GetObjectType(uninitializedObject) ?? value3.FieldType, json2));
					}
					else if (value2.TryGetValue(key, out value4))
					{
						DiscoverObjectTypeAttribute customAttribute2 = value4.GetCustomAttribute<DiscoverObjectTypeAttribute>();
						value4.SetValue(uninitializedObject, ParseValue(customAttribute2?.GetObjectType(uninitializedObject) ?? value4.PropertyType, json2), null);
					}
				}
			}
			return uninitializedObject;
		}
	}
	public static class JSONWriter
	{
		public static string ToJson(this object item)
		{
			StringBuilder stringBuilder = new StringBuilder();
			AppendValue(stringBuilder, item);
			return stringBuilder.ToString();
		}

		private static void AppendValue(StringBuilder stringBuilder, object item)
		{
			if (item == null)
			{
				stringBuilder.Append("null");
				return;
			}
			Type type = item.GetType();
			if (type == typeof(string))
			{
				stringBuilder.Append('"');
				string text = (string)item;
				for (int i = 0; i < text.Length; i++)
				{
					if (text[i] < ' ' || text[i] == '"' || text[i] == '\\')
					{
						stringBuilder.Append('\\');
						int num = "\"\\\n\r\t\b\f".IndexOf(text[i]);
						if (num >= 0)
						{
							stringBuilder.Append("\"\\nrtbf"[num]);
						}
						else
						{
							stringBuilder.AppendFormat("u{0:X4}", (uint)text[i]);
						}
					}
					else
					{
						stringBuilder.Append(text[i]);
					}
				}
				stringBuilder.Append('"');
				return;
			}
			if (type == typeof(byte) || type == typeof(int) || type == typeof(long) || type == typeof(uint) || type == typeof(ulong))
			{
				stringBuilder.Append(item.ToString());
				return;
			}
			if (type == typeof(float))
			{
				stringBuilder.Append(((float)item).ToString(CultureInfo.InvariantCulture));
				return;
			}
			if (type == typeof(double))
			{
				stringBuilder.Append(((double)item).ToString(CultureInfo.InvariantCulture));
				return;
			}
			if (type == typeof(bool))
			{
				stringBuilder.Append(((bool)item) ? "true" : "false");
				return;
			}
			if (type.IsEnum)
			{
				stringBuilder.Append('"');
				stringBuilder.Append(item.ToString());
				stringBuilder.Append('"');
				return;
			}
			if (item is IList)
			{
				stringBuilder.Append('[');
				bool flag = true;
				IList list = item as IList;
				for (int j = 0; j < list.Count; j++)
				{
					if (flag)
					{
						flag = false;
					}
					else
					{
						stringBuilder.Append(',');
					}
					AppendValue(stringBuilder, list[j]);
				}
				stringBuilder.Append(']');
				return;
			}
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >))
			{
				if (type.GetGenericArguments()[0] != typeof(string))
				{
					stringBuilder.Append("{}");
					return;
				}
				stringBuilder.Append('{');
				IDictionary dictionary = item as IDictionary;
				bool flag2 = true;
				foreach (object key in dictionary.Keys)
				{
					if (flag2)
					{
						flag2 = false;
					}
					else
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append('"');
					stringBuilder.Append((string)key);
					stringBuilder.Append("\":");
					AppendValue(stringBuilder, dictionary[key]);
				}
				stringBuilder.Append('}');
				return;
			}
			stringBuilder.Append('{');
			bool flag3 = true;
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
			for (int k = 0; k < fields.Length; k++)
			{
				if (fields[k].IsDefined(typeof(IgnoreDataMemberAttribute), inherit: true))
				{
					continue;
				}
				object value = fields[k].GetValue(item);
				if (value != null)
				{
					if (flag3)
					{
						flag3 = false;
					}
					else
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append('"');
					stringBuilder.Append(GetMemberName(fields[k]));
					stringBuilder.Append("\":");
					AppendValue(stringBuilder, value);
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
			for (int l = 0; l < properties.Length; l++)
			{
				if (!properties[l].CanRead || properties[l].IsDefined(typeof(IgnoreDataMemberAttribute), inherit: true))
				{
					continue;
				}
				object value2 = properties[l].GetValue(item, null);
				if (value2 != null)
				{
					if (flag3)
					{
						flag3 = false;
					}
					else
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append('"');
					stringBuilder.Append(GetMemberName(properties[l]));
					stringBuilder.Append("\":");
					AppendValue(stringBuilder, value2);
				}
			}
			stringBuilder.Append('}');
		}

		private static string GetMemberName(MemberInfo member)
		{
			if (member.IsDefined(typeof(DataMemberAttribute), inherit: true))
			{
				DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), inherit: true);
				if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
				{
					return dataMemberAttribute.Name;
				}
			}
			return member.Name;
		}
	}
}
namespace ProperSave
{
	public static class Extensions
	{
		public static int DifferenceCount<T>(this IEnumerable<T> collection, IEnumerable<T> second)
		{
			List<T> list = second.ToList();
			int num = 0;
			foreach (T item in collection)
			{
				if (!list.Remove(item))
				{
					num++;
				}
			}
			return num + list.Count;
		}

		public static int AddOrIndexOf<T>(this List<T> list, T value)
		{
			int num = list.IndexOf(value);
			if (num < 0)
			{
				list.Add(value);
				return list.Count - 1;
			}
			return num;
		}

		public static T GetSafe<T>(this List<T> list, int index)
		{
			if (list == null || list.Count < (uint)index)
			{
				return default(T);
			}
			return list[index];
		}
	}
	public static class LanguageConsts
	{
		public static readonly string PROPER_SAVE_TITLE_CONTINUE_DESC = "PROPER_SAVE_TITLE_CONTINUE_DESC";

		public static readonly string PROPER_SAVE_TITLE_CONTINUE = "PROPER_SAVE_TITLE_CONTINUE";

		public static readonly string PROPER_SAVE_TITLE_LOAD = "PROPER_SAVE_TITLE_LOAD";

		public static readonly string PROPER_SAVE_CHAT_SAVE = "PROPER_SAVE_CHAT_SAVE";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_SAVED = "PROPER_SAVE_QUIT_DIALOG_SAVED";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE = "PROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_NOT_SAVED = "PROPER_SAVE_QUIT_DIALOG_NOT_SAVED";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_TITLE = "PROPER_SAVE_TOOLTIP_LOAD_TITLE";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_BODY = "PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_BODY";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_CHARACTER = "PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_CHARACTER";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH = "PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH";

		public static readonly string PROPER_SAVE_CHAT_SAVE_FAILED = "PROPER_SAVE_CHAT_SAVE_FAILED";

		public static readonly string PROPER_SAVE_SELECT_SAVE_TITLE = "PROPER_SAVE_SELECT_SAVE_TITLE";

		public static readonly string PROPER_SAVE_SELECT_SAVE_DESCRIPTION = "PROPER_SAVE_SELECT_SAVE_DESCRIPTION";

		public static readonly string PROPER_SAVE_SELECT_SAVE_BUTTON = "PROPER_SAVE_SELECT_SAVE_BUTTON";

		public static readonly string PROPER_SAVE_SELECT_SAVE_CANCEL = "PROPER_SAVE_SELECT_SAVE_CANCEL";

		public static readonly string PROPER_SAVE_DELETE_SAVE = "PROPER_SAVE_DELETE_SAVE";

		public static readonly string PROPER_SAVE_DELETE_SAVE_TITLE = "PROPER_SAVE_DELETE_SAVE_TITLE";

		public static readonly string PROPER_SAVE_DELETE_SAVE_DESCRIPTION = "PROPER_SAVE_DELETE_SAVE_DESCRIPTION";

		public static readonly string PROPER_SAVE_DELETE_CONFIRM_TITLE = "PROPER_SAVE_DELETE_CONFIRM_TITLE";

		public static readonly string PROPER_SAVE_DELETE_CONFIRM_DESCRIPTION = "PROPER_SAVE_DELETE_CONFIRM_DESCRIPTION";

		public static readonly string PROPER_SAVE_DELETE_CONFIRM_YES = "PROPER_SAVE_DELETE_CONFIRM_YES";

		public static readonly string PROPER_SAVE_SELECT_HINT = "PROPER_SAVE_SELECT_HINT";

		public static readonly string PROPER_SAVE_BACK_HINT = "PROPER_SAVE_BACK_HINT";

		public static readonly string PROPER_SAVE_MOUSE_SELECT_HINT = "PROPER_SAVE_MOUSE_SELECT_HINT";

		public static readonly string PROPER_SAVE_ESC_HINT = "PROPER_SAVE_ESC_HINT";
	}
	public static class Loading
	{
		private static bool isLoading;

		public static bool IsLoading
		{
			get
			{
				return isLoading;
			}
			internal set
			{
				if (isLoading != value)
				{
					isLoading = value;
					if (isLoading)
					{
						Loading.OnLoadingStarted?.Invoke(CurrentSave);
					}
					else
					{
						Loading.OnLoadingEnded?.Invoke(CurrentSave);
					}
				}
			}
		}

		public static bool FirstRunStage { get; internal set; }

		public static SaveFile CurrentSave => ProperSavePlugin.CurrentSave?.Body;

		public static event Action<SaveFile> OnLoadingStarted;

		public static event Action<SaveFile> OnLoadingEnded;

		internal static void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Run.Start += new Manipulator(RunStart);
			TeamManager.Start += new hook_Start(TeamManagerStart);
		}

		internal static void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Run.Start -= new Manipulator(RunStart);
			TeamManager.Start -= new hook_Start(TeamManagerStart);
		}

		private static void TeamManagerStart(orig_Start orig, TeamManager self)
		{
			orig.Invoke(self);
			if (IsLoading)
			{
				CurrentSave.LoadTeam();
				IsLoading = false;
			}
		}

		private static void RunStart(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002e: 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)
			ILCursor val = new ILCursor(il);
			val.EmitDelegate<Func<bool>>((Func<bool>)delegate
			{
				FirstRunStage = true;
				if (IsLoading)
				{
					ProperSavePlugin.InstanceLogger.LogInfo((object)("Loading save file " + ProperSavePlugin.CurrentSave.FileName));
					CurrentSave.LoadRun();
					CurrentSave.LoadArtifacts();
					CurrentSave.LoadPlayers();
				}
				else
				{
					ProperSavePlugin.CurrentSave = null;
				}
				return IsLoading;
			});
			val.Emit(OpCodes.Brfalse, val.Next);
			val.Emit(OpCodes.Ret);
		}

		internal static IEnumerator LoadLobby()
		{
			SaveFileMetadata currentLobbySaveMetadata = SaveFileMetadata.GetCurrentLobbySaveMetadata();
			yield return LoadLobby(currentLobbySaveMetadata);
		}

		internal static IEnumerator LoadLobby(SaveFileMetadata metadata)
		{
			if ((Object)(object)PreGameController.instance == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"PreGameController instance not found");
				yield break;
			}
			NetworkManagerSystem singleton = NetworkManagerSystem.singleton;
			if (singleton != null && singleton.desiredHost.hostingParameters.listen && !PlatformSystems.lobbyManager.ownsLobby)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"You must be a lobby leader to load the game");
				yield break;
			}
			if (metadata == null)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Save file for current users is not found");
				yield break;
			}
			UPath? filePath = metadata.FilePath;
			if (!filePath.HasValue)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Metadata doesn't contain file name for the save file");
				yield break;
			}
			if (!ProperSavePlugin.SavesFileSystem.FileExists(filePath.Value))
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)$"File \"{filePath}\" is not found");
				yield break;
			}
			metadata.ReadBody();
			ProperSavePlugin.CurrentSave = metadata;
			IsLoading = true;
			if (metadata.Header.ContentHash != ProperSavePlugin.ContentHash)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Loading run but content mismatch detected which may result in errors");
			}
			PreGameController.instance.StartRun();
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		internal static void LoadForce(ConCommandArgs args)
		{
			string text = ((ConCommandArgs)(ref args)).TryGetArgString(0);
			if (string.IsNullOrWhiteSpace(text) || !File.Exists(text))
			{
				Debug.LogError((object)"Incorrect path");
				return;
			}
			SaveFileMetadata saveFileMetadata = new SaveFileMetadata();
			try
			{
				saveFileMetadata.ReadForce(text);
				ProperSavePlugin.CurrentSave = saveFileMetadata;
				IsLoading = true;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("Failed to load save file at path \"" + text + "\""));
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
				ResetLoading();
			}
			if (saveFileMetadata.Header.ContentHash != ProperSavePlugin.ContentHash)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Loading run but content mismatch detected which may result in errors");
			}
			if (Object.op_Implicit((Object)(object)PreGameController.instance))
			{
				if (NetworkUser.readOnlyInstancesList.Count > 0)
				{
					Debug.LogWarning((object)"Force loading only allowed for 1 player in lobby");
					ResetLoading();
				}
				else
				{
					PreGameController.instance.StartRun();
				}
			}
			else
			{
				((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(LoadForceCoroutine());
			}
			static void ResetLoading()
			{
				ProperSavePlugin.CurrentSave = null;
				IsLoading = false;
			}
		}

		private static IEnumerator LoadForceCoroutine()
		{
			Console.instance.SubmitCmd((NetworkUser)null, "host 0", false);
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)PreGameController.instance != (Object)null));
			PreGameController.instance.StartRun();
		}
	}
	internal static class LobbyUI
	{
		private class SaveDialogCloseWatcher : MonoBehaviour
		{
			public SimpleDialogBox dialog;

			public Action onCancel;

			private float delay = 0.4f;

			private bool closing;

			private void Update()
			{
				if (!closing)
				{
					delay -= Time.unscaledDeltaTime;
					if (!(delay > 0f) && (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)331)))
					{
						closing = true;
						GameObject obj = (((Object)(object)dialog.rootObject != (Object)null) ? dialog.rootObject : ((Component)dialog).gameObject);
						onCancel?.Invoke();
						Object.Destroy((Object)(object)obj);
					}
				}
			}
		}

		private class CompactSaveDialogButton : MonoBehaviour
		{
		}

		private class SaveDialogInputLegendController : MonoBehaviour
		{
			public MPEventSystem eventSystem;

			public InputBindingDisplayController selectGlyph;

			public InputBindingDisplayController backGlyph;

			private void Update()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Invalid comparison between Unknown and I4
				bool visible = (Object)(object)eventSystem != (Object)null && (int)eventSystem.currentInputSource == 1;
				SetGlyphVisible(selectGlyph, visible);
				SetGlyphVisible(backGlyph, visible);
			}

			private static void SetGlyphVisible(InputBindingDisplayController glyph, bool visible)
			{
				if (!((Object)(object)glyph == (Object)null))
				{
					HGTextMeshProUGUI component = ((Component)glyph).GetComponent<HGTextMeshProUGUI>();
					if ((Object)(object)component != (Object)null)
					{
						((Behaviour)component).enabled = visible;
					}
					Transform val = ((Component)glyph).transform.parent.Find("KeyFallback");
					if ((Object)(object)val != (Object)null)
					{
						((Component)val).gameObject.SetActive(!visible);
					}
				}
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__24_1;

			public static UnityAction <>9__25_0;

			public static UnityAction <>9__26_1;

			public static Action <>9__26_2;

			public static Func<MPButton, bool> <>9__33_0;

			public static Func<MPButton, Transform> <>9__33_1;

			public static Func<MPButton, bool> <>9__34_0;

			internal void <ShowSaveSelectionDialog>b__24_1()
			{
			}

			internal void <ShowDeleteSaveDialog>b__25_0()
			{
			}

			internal void <ShowDeleteConfirmDialog>b__26_1()
			{
				ShowSaveSelectionDialog(SaveFileMetadata.GetCurrentLobbySaveMetadatas());
			}

			internal void <ShowDeleteConfirmDialog>b__26_2()
			{
				ShowSaveSelectionDialog(SaveFileMetadata.GetCurrentLobbySaveMetadatas());
			}

			internal bool <ApplyConfirmDialogLayout>b__33_0(MPButton button)
			{
				return (Object)(object)((Component)button).GetComponentInParent<SaveDialogInputLegendController>() == (Object)null;
			}

			internal Transform <ApplyConfirmDialogLayout>b__33_1(MPButton button)
			{
				return ((Component)button).transform;
			}

			internal bool <WrapSaveDialogNavigation>b__34_0(MPButton button)
			{
				return (Object)(object)((Component)button).GetComponentInParent<SaveDialogInputLegendController>() == (Object)null;
			}
		}

		private static GameObject lobbyButton;

		private static GameObject lobbySubmenuLegend;

		private static GameObject lobbyGlyphAndDescription;

		private static TooltipProvider tooltipProvider;

		private static GamepadTooltipProvider gamepadTooltipProvider;

		private static SaveFileMetadata lastFileMetadata;

		private static TooltipContent lastTooltipContent;

		private const float DialogWidth = 640f;

		private const float SaveButtonHeight = 86f;

		private const float CompactButtonHeight = 52f;

		private const float LegendHeight = 42f;

		private const float ConfirmRowHeight = 56f;

		private const float ConfirmButtonWidth = 230f;

		private const float ConfirmButtonHeight = 48f;

		private const float LegendItemWidth = 260f;

		private const float LegendItemHeight = 30f;

		public static void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			CharacterSelectController.Awake += new hook_Awake(CharacterSelectControllerAwake);
			NetworkUser.onPostNetworkUserStart += new NetworkUserGenericDelegate(NetworkUserOnPostNetworkUserStart);
			NetworkUser.onNetworkUserLost += new NetworkUserGenericDelegate(NetworkUserOnNetworkUserLost);
		}

		public static void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			CharacterSelectController.Awake -= new hook_Awake(CharacterSelectControllerAwake);
			NetworkUser.onPostNetworkUserStart -= new NetworkUserGenericDelegate(NetworkUserOnPostNetworkUserStart);
			NetworkUser.onNetworkUserLost -= new NetworkUserGenericDelegate(NetworkUserOnNetworkUserLost);
		}

		private static void NetworkUserOnNetworkUserLost(NetworkUser networkUser)
		{
			UpdateLobbyControls(networkUser);
		}

		private static void NetworkUserOnPostNetworkUserStart(NetworkUser networkUser)
		{
			UpdateLobbyControls();
		}

		private static void CharacterSelectControllerAwake(orig_Awake orig, CharacterSelectController self)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Invalid comparison between Unknown and I4
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Expected O, but got Unknown
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Expected O, but got Unknown
			try
			{
				GameObject gameObject = ((Component)((Component)self).transform.GetChild(2).GetChild(4).GetChild(0)).gameObject;
				lobbyButton = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
				InputSourceFilter[] components = ((Component)self).GetComponents<InputSourceFilter>();
				foreach (InputSourceFilter val in components)
				{
					if ((int)val.requiredInputSource == 0)
					{
						Array.Resize(ref val.objectsToFilter, val.objectsToFilter.Length + 1);
						val.objectsToFilter[val.objectsToFilter.Length - 1] = lobbyButton;
						break;
					}
				}
				((Object)lobbyButton).name = "[CENI] Load";
				tooltipProvider = lobbyButton.AddComponent<TooltipProvider>();
				RectTransform component = lobbyButton.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(1f, 1.5f);
				component.anchorMax = new Vector2(1f, 1.5f);
				HGButton component2 = lobbyButton.GetComponent<HGButton>();
				component2.hoverToken = LanguageConsts.PROPER_SAVE_TITLE_CONTINUE_DESC;
				lobbyButton.GetComponent<LanguageTextMeshController>().token = LanguageConsts.PROPER_SAVE_TITLE_LOAD;
				((Button)component2).onClick = new ButtonClickedEvent();
				((UnityEvent)((Button)component2).onClick).AddListener(new UnityAction(LoadOnInputEvent));
				GameObject gameObject2 = ((Component)((Component)self).transform.GetChild(2).GetChild(4).GetChild(1)).gameObject;
				lobbySubmenuLegend = Object.Instantiate<GameObject>(gameObject2, gameObject2.transform.parent);
				components = ((Component)self).GetComponents<InputSourceFilter>();
				foreach (InputSourceFilter val2 in components)
				{
					if ((int)val2.requiredInputSource == 1)
					{
						Array.Resize(ref val2.objectsToFilter, val2.objectsToFilter.Length + 1);
						val2.objectsToFilter[val2.objectsToFilter.Length - 1] = lobbySubmenuLegend;
						break;
					}
				}
				((Object)lobbySubmenuLegend).name = "[CENI] SubmenuLegend";
				UIJuice component3 = lobbySubmenuLegend.GetComponent<UIJuice>();
				OnEnableEvent component4 = lobbySubmenuLegend.GetComponent<OnEnableEvent>();
				((UnityEventBase)component4.action).RemoveAllListeners();
				component4.action.AddListener(new UnityAction(component3.TransitionPanFromTop));
				component4.action.AddListener(new UnityAction(component3.TransitionAlphaFadeIn));
				RectTransform component5 = lobbySubmenuLegend.GetComponent<RectTransform>();
				component5.anchorMin = new Vector2(1f, 1f);
				component5.anchorMax = new Vector2(1f, 2f);
				lobbyGlyphAndDescription = ((Component)lobbySubmenuLegend.transform.GetChild(0)).gameObject;
				lobbyGlyphAndDescription.SetActive(true);
				InputBindingDisplayController component6 = ((Component)lobbyGlyphAndDescription.transform.GetChild(0)).GetComponent<InputBindingDisplayController>();
				component6.actionName = "UISubmitTertiary";
				Transform child = lobbyGlyphAndDescription.transform.GetChild(1);
				LanguageTextMeshController component7 = ((Component)lobbyGlyphAndDescription.transform.GetChild(2)).GetComponent<LanguageTextMeshController>();
				Object.Destroy((Object)(object)((Component)child).gameObject);
				component7.token = LanguageConsts.PROPER_SAVE_TITLE_LOAD;
				for (int j = 1; j < lobbySubmenuLegend.transform.childCount; j++)
				{
					Object.Destroy((Object)(object)((Component)lobbySubmenuLegend.transform.GetChild(j)).gameObject);
				}
				HoldGamepadInputEvent holdGamepadInputEvent = ((Component)self).gameObject.AddComponent<HoldGamepadInputEvent>();
				((HGGamepadInputEvent)holdGamepadInputEvent).actionName = "UISubmitTertiary";
				((HGGamepadInputEvent)holdGamepadInputEvent).enabledObjectsIfActive = Array.Empty<GameObject>();
				((HGGamepadInputEvent)holdGamepadInputEvent).actionEvent = new UnityEvent();
				((HGGamepadInputEvent)holdGamepadInputEvent).actionEvent.AddListener(new UnityAction(LoadOnInputEvent));
				gamepadTooltipProvider = ((Component)component6).gameObject.AddComponent<GamepadTooltipProvider>();
				gamepadTooltipProvider.inputEvent = holdGamepadInputEvent;
				UpdateLobbyControls();
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed while adding lobby buttons");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
			orig.Invoke(self);
		}

		private static void LoadOnInputEvent()
		{
			if ((Object)(object)Run.instance != (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Can't load while run is active");
				return;
			}
			if (Loading.IsLoading)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Already loading");
				return;
			}
			List<SaveFileMetadata> currentLobbySaveMetadatas = SaveFileMetadata.GetCurrentLobbySaveMetadatas();
			if (currentLobbySaveMetadatas.Count == 0)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Save file for current users is not found");
			}
			else
			{
				ShowSaveSelectionDialog(currentLobbySaveMetadatas);
			}
		}

		private static void UpdateLobbyControls(NetworkUser exceptUser = null)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			SaveFileMetadata currentLobbySaveMetadata = SaveFileMetadata.GetCurrentLobbySaveMetadata(exceptUser);
			bool flag = PlatformSystems.lobbyManager.isInLobby == PlatformSystems.lobbyManager.ownsLobby && currentLobbySaveMetadata != null && currentLobbySaveMetadata.FilePath.HasValue && ProperSavePlugin.SavesFileSystem.FileExists(currentLobbySaveMetadata.FilePath.Value);
			if (currentLobbySaveMetadata != lastFileMetadata)
			{
				lastFileMetadata = currentLobbySaveMetadata;
				try
				{
					if (currentLobbySaveMetadata != null)
					{
						lastTooltipContent = new TooltipContent
						{
							titleToken = LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_TITLE,
							overrideBodyText = GetSaveDescription(currentLobbySaveMetadata),
							titleColor = Color.black,
							disableBodyRichText = false
						};
					}
					else
					{
						lastTooltipContent = default(TooltipContent);
					}
				}
				catch (Exception ex)
				{
					ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to get information about save file");
					ProperSavePlugin.InstanceLogger.LogError((object)ex);
					flag = false;
				}
			}
			try
			{
				if (Object.op_Implicit((Object)(object)lobbyButton))
				{
					HGButton component = lobbyButton.GetComponent<HGButton>();
					if (Object.op_Implicit((Object)(object)component))
					{
						((Selectable)component).interactable = flag;
					}
				}
				if (Object.op_Implicit((Object)(object)tooltipProvider))
				{
					tooltipProvider.SetContent(lastTooltipContent);
				}
			}
			catch
			{
			}
			try
			{
				if (Object.op_Implicit((Object)(object)lobbyGlyphAndDescription))
				{
					Color color = (Color)(flag ? Color.white : new Color(0.3f, 0.3f, 0.3f));
					((Graphic)((Component)lobbyGlyphAndDescription.transform.GetChild(0)).GetComponent<HGTextMeshProUGUI>()).color = color;
					((Graphic)((Component)lobbyGlyphAndDescription.transform.GetChild(1)).GetComponent<HGTextMeshProUGUI>()).color = color;
				}
				if (Object.op_Implicit((Object)(object)gamepadTooltipProvider))
				{
					((TooltipProvider)gamepadTooltipProvider).SetContent(lastTooltipContent);
				}
			}
			catch
			{
			}
		}

		private static string GetSaveDescription(SaveFileMetadata saveMetadata)
		{
			//IL_0050: 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)
			SaveFileHeader header = saveMetadata.Header;
			StringBuilder stringBuilder = new StringBuilder();
			HeaderUserData[] users = header.Users;
			foreach (HeaderUserData userData in users)
			{
				NetworkUser val = ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)delegate(NetworkUser user)
				{
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					NetworkUserId val3 = userData.UserId.Load();
					return ((NetworkUserId)(ref val3)).Equals(user.id);
				});
				SurvivorDef val2 = SurvivorCatalog.FindSurvivorDefFromBody(BodyCatalog.GetBodyPrefab(userData.Body));
				stringBuilder.Append(Language.GetStringFormatted(LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_CHARACTER, new object[2]
				{
					val?.userName,
					((Object)(object)val2 != (Object)null) ? Language.GetString(val2.displayNameToken) : ""
				}));
			}
			SceneDef sceneDefFromSceneName = SceneCatalog.GetSceneDefFromSceneName(header.SceneName);
			DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(header.Difficulty);
			int time = header.Time;
			int stageClearCount = header.StageClearCount;
			return Language.GetStringFormatted(LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_BODY, new object[6]
			{
				stringBuilder.ToString(),
				Object.op_Implicit((Object)(object)sceneDefFromSceneName) ? Language.GetString(sceneDefFromSceneName.nameToken) : "",
				(stageClearCount + 1).ToString(),
				$"{time / 60:00}:{time % 60:00}",
				(difficultyDef != null) ? Language.GetString(difficultyDef.nameToken) : "",
				(header.ContentHash != ProperSavePlugin.ContentHash) ? Language.GetString(LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH) : ""
			});
		}

		private static void ShowSaveSelectionDialog(List<SaveFileMetadata> saves)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			EventSystem current = EventSystem.current;
			SimpleDialogBox val = SimpleDialogBox.Create((MPEventSystem)(object)((current is MPEventSystem) ? current : null));
			if ((Object)(object)val == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to create save selection dialog");
				return;
			}
			val.headerToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_SELECT_SAVE_TITLE
			};
			val.descriptionToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_SELECT_SAVE_DESCRIPTION
			};
			foreach (SaveFileMetadata safe in saves)
			{
				SaveFileMetadata captured = safe;
				val.AddActionButton((UnityAction)delegate
				{
					((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(Loading.LoadLobby(captured));
				}, LanguageConsts.PROPER_SAVE_TITLE_LOAD, true, Array.Empty<object>());
				SetLastButtonContent(val, GetSaveButtonDescription(safe), GetSavePortrait(safe));
			}
			val.AddActionButton((UnityAction)delegate
			{
				ShowDeleteSaveDialog(saves);
			}, LanguageConsts.PROPER_SAVE_DELETE_SAVE, true, Array.Empty<object>());
			MarkLastButtonCompact(val);
			object obj = <>c.<>9__24_1;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
				};
				<>c.<>9__24_1 = val2;
				obj = (object)val2;
			}
			val.AddActionButton((UnityAction)obj, LanguageConsts.PROPER_SAVE_SELECT_SAVE_CANCEL, true, Array.Empty<object>());
			MarkLastButtonCompact(val);
			AddCloseWatcher(val);
			((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(DelayedSaveDialogLayout(val));
		}

		private static void ShowDeleteSaveDialog(List<SaveFileMetadata> saves)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			EventSystem current = EventSystem.current;
			SimpleDialogBox val = SimpleDialogBox.Create((MPEventSystem)(object)((current is MPEventSystem) ? current : null));
			if ((Object)(object)val == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to create delete save dialog");
				return;
			}
			val.headerToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_DELETE_SAVE_TITLE
			};
			val.descriptionToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_DELETE_SAVE_DESCRIPTION
			};
			foreach (SaveFileMetadata safe in saves)
			{
				SaveFileMetadata captured = safe;
				val.AddActionButton((UnityAction)delegate
				{
					ShowDeleteConfirmDialog(captured);
				}, LanguageConsts.PROPER_SAVE_DELETE_SAVE, true, Array.Empty<object>());
				SetLastButtonContent(val, GetSaveButtonDescription(safe), GetSavePortrait(safe));
			}
			object obj = <>c.<>9__25_0;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
				};
				<>c.<>9__25_0 = val2;
				obj = (object)val2;
			}
			val.AddActionButton((UnityAction)obj, LanguageConsts.PROPER_SAVE_SELECT_SAVE_CANCEL, true, Array.Empty<object>());
			MarkLastButtonCompact(val);
			AddCloseWatcher(val);
			((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(DelayedSaveDialogLayout(val));
		}

		private static void ShowDeleteConfirmDialog(SaveFileMetadata save)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_009f: 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_00aa: Expected O, but got Unknown
			EventSystem current = EventSystem.current;
			SimpleDialogBox val = SimpleDialogBox.Create((MPEventSystem)(object)((current is MPEventSystem) ? current : null));
			if ((Object)(object)val == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to create delete confirmation dialog");
				return;
			}
			val.headerToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_DELETE_CONFIRM_TITLE
			};
			val.descriptionToken = new TokenParamsPair
			{
				token = LanguageConsts.PROPER_SAVE_DELETE_CONFIRM_DESCRIPTION
			};
			val.AddActionButton((UnityAction)delegate
			{
				SaveFileMetadata.DeleteSave(save);
				UpdateLobbyControls();
			}, LanguageConsts.PROPER_SAVE_DELETE_CONFIRM_YES, true, Array.Empty<object>());
			object obj = <>c.<>9__26_1;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
					ShowSaveSelectionDialog(SaveFileMetadata.GetCurrentLobbySaveMetadatas());
				};
				<>c.<>9__26_1 = val2;
				obj = (object)val2;
			}
			val.AddActionButton((UnityAction)obj, LanguageConsts.PROPER_SAVE_SELECT_SAVE_CANCEL, true, Array.Empty<object>());
			AddCloseWatcher(val, delegate
			{
				ShowSaveSelectionDialog(SaveFileMetadata.GetCurrentLobbySaveMetadatas());
			});
			((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(DelayedSaveDialogLayout(val, confirmLayout: true));
		}

		private static string GetSaveButtonDescription(SaveFileMetadata saveMetadata)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			SaveFileHeader header = saveMetadata.Header;
			string text = "";
			if (header.Users.Length != 0)
			{
				SurvivorDef val = SurvivorCatalog.FindSurvivorDefFromBody(BodyCatalog.GetBodyPrefab(header.Users[0].Body));
				text = (((Object)(object)val != (Object)null) ? Language.GetString(val.displayNameToken) : "");
			}
			SceneDef sceneDefFromSceneName = SceneCatalog.GetSceneDefFromSceneName(header.SceneName);
			DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(header.Difficulty);
			int time = header.Time;
			return Language.GetStringFormatted(LanguageConsts.PROPER_SAVE_SELECT_SAVE_BUTTON, new object[6]
			{
				text,
				Object.op_Implicit((Object)(object)sceneDefFromSceneName) ? Language.GetString(sceneDefFromSceneName.nameToken) : header.SceneName,
				(header.StageClearCount + 1).ToString(),
				$"{time / 60:00}:{time % 60:00}",
				(difficultyDef != null) ? Language.GetString(difficultyDef.nameToken) : "",
				""
			});
		}

		private static Texture GetSavePortrait(SaveFileMetadata saveMetadata)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SaveFileHeader header = saveMetadata.Header;
				if (header.Users.Length == 0)
				{
					return null;
				}
				GameObject bodyPrefab = BodyCatalog.GetBodyPrefab(header.Users[0].Body);
				CharacterBody val = (Object.op_Implicit((Object)(object)bodyPrefab) ? bodyPrefab.GetComponent<CharacterBody>() : null);
				return Object.op_Implicit((Object)(object)val) ? val.portraitIcon : null;
			}
			catch
			{
				return null;
			}
		}

		private static void SetLastButtonContent(SimpleDialogBox dialog, string text, Texture portrait)
		{
			//IL_00b2: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform buttonContainer = dialog.buttonContainer;
				if ((Object)(object)buttonContainer == (Object)null || ((Transform)buttonContainer).childCount == 0)
				{
					return;
				}
				Transform child = ((Transform)buttonContainer).GetChild(((Transform)buttonContainer).childCount - 1);
				if ((Object)(object)portrait != (Object)null)
				{
					AddPortraitToButton(child, portrait);
				}
				LanguageTextMeshController[] componentsInChildren = ((Component)child).GetComponentsInChildren<LanguageTextMeshController>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
				HGTextMeshProUGUI componentInChildren = ((Component)child).GetComponentInChildren<HGTextMeshProUGUI>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = text;
					((TMP_Text)componentInChildren).enableWordWrapping = true;
					((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4097;
					((TMP_Text)componentInChildren).fontSize = 18f;
					RectTransform component = ((Component)componentInChildren).GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null && (Object)(object)portrait != (Object)null)
					{
						component.offsetMin = new Vector2(component.offsetMin.x + 78f, component.offsetMin.y);
					}
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to set save button content");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		private static void AddPortraitToButton(Transform button, Texture portrait)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("[CENI] Portrait", new Type[2]
			{
				typeof(RectTransform),
				typeof(RawImage)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(button, false);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.anchorMax = new Vector2(0f, 0.5f);
			component.pivot = new Vector2(0f, 0.5f);
			component.anchoredPosition = new Vector2(12f, 0f);
			component.sizeDelta = new Vector2(64f, 64f);
			RawImage component2 = val.GetComponent<RawImage>();
			component2.texture = portrait;
			((Graphic)component2).color = Color.white;
			((Graphic)component2).raycastTarget = false;
		}

		private static IEnumerator DelayedSaveDialogLayout(SimpleDialogBox dialog, bool confirmLayout = false)
		{
			yield return null;
			if (confirmLayout)
			{
				ApplyConfirmDialogLayout(dialog);
			}
			else
			{
				ApplySaveDialogLayout(dialog);
			}
		}

		private static void ApplySaveDialogLayout(SimpleDialogBox dialog)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform buttonContainer = dialog.buttonContainer;
				if ((Object)(object)buttonContainer == (Object)null)
				{
					return;
				}
				AddInputLegend(dialog);
				LayoutGroup[] components = ((Component)buttonContainer).GetComponents<LayoutGroup>();
				foreach (LayoutGroup obj in components)
				{
					((Behaviour)obj).enabled = false;
					Object.DestroyImmediate((Object)(object)obj, true);
				}
				VerticalLayoutGroup obj2 = ((Component)buttonContainer).gameObject.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f;
				((LayoutGroup)obj2).childAlignment = (TextAnchor)1;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				for (int j = 0; j < ((Transform)buttonContainer).childCount; j++)
				{
					Transform child = ((Transform)buttonContainer).GetChild(j);
					if ((Object)(object)((Component)child).GetComponent<SaveDialogInputLegendController>() != (Object)null)
					{
						ConfigureInputLegendLayout(child);
						continue;
					}
					float num = (((Object)(object)((Component)child).GetComponent<CompactSaveDialogButton>() != (Object)null) ? 52f : 86f);
					RectTransform component = ((Component)child).GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null)
					{
						component.sizeDelta = new Vector2(640f, num);
					}
					SetLayoutElement(((Component)child).gameObject, 640f, num);
				}
				ContentSizeFitter obj3 = ((Component)buttonContainer).GetComponent<ContentSizeFitter>() ?? ((Component)buttonContainer).gameObject.AddComponent<ContentSizeFitter>();
				obj3.verticalFit = (FitMode)2;
				obj3.horizontalFit = (FitMode)2;
				WrapSaveDialogNavigation(buttonContainer);
				LayoutRebuilder.ForceRebuildLayoutImmediate(buttonContainer);
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to apply save selection layout");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		private static void ApplyConfirmDialogLayout(SimpleDialogBox dialog)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform buttonContainer = dialog.buttonContainer;
				if ((Object)(object)buttonContainer == (Object)null)
				{
					return;
				}
				AddInputLegend(dialog);
				LayoutGroup[] components = ((Component)buttonContainer).GetComponents<LayoutGroup>();
				foreach (LayoutGroup obj in components)
				{
					((Behaviour)obj).enabled = false;
					Object.DestroyImmediate((Object)(object)obj, true);
				}
				List<Transform> list = (from button in ((Component)buttonContainer).GetComponentsInChildren<MPButton>(true)
					where (Object)(object)((Component)button).GetComponentInParent<SaveDialogInputLegendController>() == (Object)null
					select ((Component)button).transform).Distinct().ToList();
				Transform obj2 = ((Transform)buttonContainer).Find("[CENI] Confirm Button Row");
				RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
				if ((Object)(object)val == (Object)null)
				{
					val = new GameObject("[CENI] Confirm Button Row", new Type[3]
					{
						typeof(RectTransform),
						typeof(HorizontalLayoutGroup),
						typeof(LayoutElement)
					}).GetComponent<RectTransform>();
					((Transform)val).SetParent((Transform)(object)buttonContainer, false);
					((Transform)val).SetSiblingIndex(0);
				}
				SetCenteredRect(val, 640f, 56f);
				foreach (Transform item in list)
				{
					item.SetParent((Transform)(object)val, false);
				}
				HorizontalLayoutGroup component = ((Component)val).GetComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component).spacing = 96f;
				((LayoutGroup)component).childAlignment = (TextAnchor)4;
				((HorizontalOrVerticalLayoutGroup)component).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)component).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
				SetLayoutElement(((Component)val).gameObject, 640f, 56f);
				foreach (Transform item2 in list)
				{
					RectTransform component2 = ((Component)item2).GetComponent<RectTransform>();
					if ((Object)(object)component2 != (Object)null)
					{
						SetCenteredRect(component2, 230f, 48f);
					}
					SetLayoutElement(((Component)item2).gameObject, 230f, 48f);
				}
				VerticalLayoutGroup obj3 = ((Component)buttonContainer).gameObject.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj3).spacing = 8f;
				((LayoutGroup)obj3).childAlignment = (TextAnchor)1;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
				ConfigureInputLegendLayout(((Transform)buttonContainer).Find("[CENI] Save Input Legend"));
				ContentSizeFitter obj4 = ((Component)buttonContainer).GetComponent<ContentSizeFitter>() ?? ((Component)buttonContainer).gameObject.AddComponent<ContentSizeFitter>();
				obj4.verticalFit = (FitMode)2;
				obj4.horizontalFit = (FitMode)2;
				WrapSaveDialogNavigation(buttonContainer);
				LayoutRebuilder.ForceRebuildLayoutImmediate(buttonContainer);
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to apply delete confirmation layout");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		private static void WrapSaveDialogNavigation(RectTransform container)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			List<MPButton> list = (from button in ((Component)container).GetComponentsInChildren<MPButton>()
				where (Object)(object)((Component)button).GetComponentInParent<SaveDialogInputLegendController>() == (Object)null
				select button).ToList();
			if (list.Count != 0)
			{
				for (int num = 0; num < list.Count; num++)
				{
					Navigation val = default(Navigation);
					((Navigation)(ref val)).mode = (Mode)4;
					Navigation navigation = val;
					((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)list[(num - 1 + list.Count) % list.Count];
					((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)list[(num + 1) % list.Count];
					((Navigation)(ref navigation)).selectOnLeft = ((Navigation)(ref navigation)).selectOnUp;
					((Navigation)(ref navigation)).selectOnRight = ((Navigation)(ref navigation)).selectOnDown;
					((Selectable)list[num]).navigation = navigation;
				}
			}
		}

		private static void AddInputLegend(SimpleDialogBox dialog)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			RectTransform val = dialog?.buttonContainer;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Transform)val).Find("[CENI] Save Input Legend") != (Object)null))
			{
				GameObject val2 = new GameObject("[CENI] Save Input Legend", new Type[3]
				{
					typeof(RectTransform),
					typeof(HorizontalLayoutGroup),
					typeof(SaveDialogInputLegendController)
				});
				RectTransform component = val2.GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)val, false);
				component.sizeDelta = new Vector2(640f, 42f);
				ConfigureInputLegendLayout(val2.transform);
				HorizontalLayoutGroup component2 = val2.GetComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component2).spacing = 74f;
				((LayoutGroup)component2).padding = new RectOffset(10, 0, 8, 0);
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
				SaveDialogInputLegendController component3 = val2.GetComponent<SaveDialogInputLegendController>();
				ref MPEventSystem eventSystem = ref component3.eventSystem;
				EventSystem current = EventSystem.current;
				eventSystem = (MPEventSystem)(object)((current is MPEventSystem) ? current : null);
				component3.selectGlyph = AddLegendItem(component, "UISubmit", LanguageConsts.PROPER_SAVE_MOUSE_SELECT_HINT, LanguageConsts.PROPER_SAVE_SELECT_HINT);
				component3.backGlyph = AddLegendItem(component, "UICancel", LanguageConsts.PROPER_SAVE_ESC_HINT, LanguageConsts.PROPER_SAVE_BACK_HINT);
			}
		}

		private static void ConfigureInputLegendLayout(Transform legend)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)legend == (Object)null))
			{
				RectTransform component = ((Component)legend).GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					component.sizeDelta = new Vector2(640f, 42f);
				}
				SetLayoutElement(((Component)legend).gameObject, 640f, 42f);
			}
		}

		private static InputBindingDisplayController AddLegendItem(RectTransform parent, string actionName, string keyToken, string textToken)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(actionName + " Legend", new Type[3]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup),
				typeof(LayoutElement)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)parent, false);
			component.sizeDelta = new Vector2(260f, 30f);
			HorizontalLayoutGroup component2 = val.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 7f;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
			ConfigureLayoutElement(val.GetComponent<LayoutElement>(), 260f, 30f);
			GameObject val2 = new GameObject("Glyph", new Type[1] { typeof(RectTransform) });
			val2.SetActive(false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			((Transform)component3).SetParent((Transform)(object)component, false);
			component3.sizeDelta = new Vector2(28f, 28f);
			HGTextMeshProUGUI obj = val2.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)obj).fontSize = 18f;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			InputBindingDisplayController val3 = val2.AddComponent<InputBindingDisplayController>();
			val3.actionName = actionName;
			val3.useExplicitInputSource = true;
			val3.explicitInputSource = (InputSource)1;
			val2.SetActive(true);
			GameObject val4 = new GameObject("KeyFallback", new Type[1] { typeof(RectTransform) });
			val4.SetActive(false);
			RectTransform component4 = val4.GetComponent<RectTransform>();
			((Transform)component4).SetParent((Transform)(object)component, false);
			component4.sizeDelta = new Vector2(160f, 28f);
			HGTextMeshProUGUI obj2 = val4.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)obj2).fontSize = 14f;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)obj2).enableWordWrapping = false;
			val4.AddComponent<LanguageTextMeshController>().token = keyToken;
			val4.SetActive(true);
			GameObject val5 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
			val5.SetActive(false);
			RectTransform component5 = val5.GetComponent<RectTransform>();
			((Transform)component5).SetParent((Transform)(object)component, false);
			component5.sizeDelta = new Vector2(90f, 28f);
			HGTextMeshProUGUI obj3 = val5.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)obj3).fontSize = 14f;
			((TMP_Text)obj3).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)obj3).enableWordWrapping = false;
			val5.AddComponent<LanguageTextMeshController>().token = textToken;
			val5.SetActive(true);
			return val3;
		}

		private static SaveDialogCloseWatcher AddCloseWatcher(SimpleDialogBox dialog, Action onCancel = null)
		{
			SaveDialogCloseWatcher saveDialogCloseWatcher = GetDialogRoot(dialog).AddComponent<SaveDialogCloseWatcher>();
			saveDialogCloseWatcher.dialog = dialog;
			saveDialogCloseWatcher.onCancel = onCancel;
			return saveDialogCloseWatcher;
		}

		private static GameObject GetDialogRoot(SimpleDialogBox dialog)
		{
			if (!((Object)(object)dialog.rootObject != (Object)null))
			{
				return ((Component)dialog).gameObject;
			}
			return dialog.rootObject;
		}

		private static void SetCenteredRect(RectTransform rect, float width, float height)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			rect.anchorMin = new Vector2(0.5f, 0.5f);
			rect.anchorMax = new Vector2(0.5f, 0.5f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.anchoredPosition = Vector2.zero;
			rect.sizeDelta = new Vector2(width, height);
		}

		private static void SetLayoutElement(GameObject target, float width, float height)
		{
			ConfigureLayoutElement(target.GetComponent<LayoutElement>() ?? target.AddComponent<LayoutElement>(), width, height);
		}

		private static void ConfigureLayoutElement(LayoutElement element, float width, float height)
		{
			element.minWidth = width;
			element.preferredWidth = width;
			element.minHeight = height;
			element.preferredHeight = height;
			element.flexibleWidth = 0f;
			element.flexibleHeight = 0f;
		}

		private static void MarkLastButtonCompact(SimpleDialogBox dialog)
		{
			RectTransform val = dialog?.buttonContainer;
			if (!((Object)(object)val == (Object)null) && ((Transform)val).childCount != 0)
			{
				Transform child = ((Transform)val).GetChild(((Transform)val).childCount - 1);
				if ((Object)(object)((Component)child).GetComponent<CompactSaveDialogButton>() == (Object)null)
				{
					((Component)child).gameObject.AddComponent<CompactSaveDialogButton>();
				}
			}
		}
	}
	internal class LostNetworkUser : MonoBehaviour
	{
		private static readonly Dictionary<CharacterMaster, LostNetworkUser> lostUsers = new Dictionary<CharacterMaster, LostNetworkUser>();

		private CharacterMaster master;

		public uint lunarCoins;

		public NetworkUserId userID;

		public BodyIndex bodyIndexPreference;

		private void Awake()
		{
			master = ((Component)this).GetComponent<CharacterMaster>();
			lostUsers[master] = this;
		}

		private void OnDestroy()
		{
			lostUsers.Remove(master);
		}

		public static bool TryGetUser(CharacterMaster master, out LostNetworkUser lostUser)
		{
			if (!Object.op_Implicit((Object)(object)master) || !lostUsers.TryGetValue(master, out lostUser))
			{
				lostUser = null;
				return false;
			}
			return true;
		}

		public static void Subscribe()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			NetworkUser.onNetworkUserLost += new NetworkUserGenericDelegate(OnNetworkUserLost);
		}

		public static void Unsubscribe()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			NetworkUser.onNetworkUserLost -= new NetworkUserGenericDelegate(OnNetworkUserLost);
		}

		private static void OnNetworkUserLost(NetworkUser networkUser)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)networkUser.master))
			{
				LostNetworkUser lostNetworkUser = ((Component)networkUser.master).gameObject.AddComponent<LostNetworkUser>();
				lostNetworkUser.lunarCoins = networkUser.lunarCoins;
				lostNetworkUser.userID = networkUser.id;
				lostNetworkUser.bodyIndexPreference = networkUser.bodyIndexPreference;
			}
		}
	}
	internal static class ModCompat
	{
		public const string BiggerBazaarGUID = "com.MagnusMagnuson.BiggerBazaar";

		public const string ShareSuiteGUID = "com.funkfrog_sipondo.sharesuite";

		public static bool IsBBLoaded { get; private set; }

		public static bool IsSSLoaded { get; private set; }

		public static bool IsR2APIDifficultyLoaded { get; private set; }

		private static Dictionary<MethodInfo, Action<ILContext>> RegisteredILHooks { get; } = new Dictionary<MethodInfo, Action<ILContext>>();

		public static void GatherLoadedPlugins()
		{
			IsBBLoaded = Chainloader.PluginInfos.ContainsKey("com.MagnusMagnuson.BiggerBazaar");
			IsSSLoaded = Chainloader.PluginInfos.ContainsKey("com.funkfrog_sipondo.sharesuite");
			IsR2APIDifficultyLoaded = Chainloader.PluginInfos.ContainsKey("com.bepis.r2api.difficulty");
		}

		public static void RegisterHooks()
		{
			if (IsBBLoaded)
			{
				try
				{
					RegisterBBHooks();
				}
				catch (Exception ex)
				{
					ProperSavePlugin.InstanceLogger.LogError((object)"Failed to add support for BiggerBazaar");
					ProperSavePlugin.InstanceLogger.LogError((object)ex);
				}
			}
		}

		public static void UnregisterHooks()
		{
			foreach (KeyValuePair<MethodInfo, Action<ILContext>> registeredILHook in RegisteredILHooks)
			{
				HookEndpointManager.Unmodify((MethodBase)registeredILHook.Key, (Delegate)registeredILHook.Value);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterBBHooks()
		{
			MethodInfo method = typeof(BiggerBazaar).Assembly.GetType("BiggerBazaar.Bazaar").GetMethod("StartBazaar", BindingFlags.Instance | BindingFlags.Public);
			Action<ILContext> action = BBHook;
			HookEndpointManager.Modify((MethodBase)method, (Delegate)action);
			RegisteredILHooks.Add(method, action);
		}

		private static void BBHook(ILContext il)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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)
			Type type = typeof(BiggerBazaar).Assembly.GetType("BiggerBazaar.Bazaar");
			ILCursor val = new ILCursor(il);
			int index = val.Index;
			val.Index = index + 1;
			Instruction next = val.Next;
			val.Emit(OpCodes.Call, (MethodBase)typeof(Loading).GetProperty("FirstRunStage").GetGetMethod());
			val.Emit(OpCodes.Brfalse, next);
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Call, (MethodBase)type.GetMethod("ResetBazaarPlayers"));
			val.Emit(OpCodes.Ldarg_0);
			val.Emit(OpCodes.Call, (MethodBase)type.GetMethod("CalcDifficultyCoefficient"));
		}

		public static void LoadShareSuiteMoney(uint money)
		{
			try
			{
				if (IsSSLoaded)
				{
					((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(LoadShareSuiteMoneyInternal(money));
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static IEnumerator LoadShareSuiteMoneyInternal(uint money)
		{
			yield return (object)new WaitUntil((Func<bool>)(() => !MoneySharingHooks.MapTransitionActive));
			MoneySharingHooks.SharedMoneyValue = (int)money;
		}

		public static void ShareSuiteMapTransition()
		{
			try
			{
				if (IsSSLoaded)
				{
					ShareSuiteMapTransitionInternal();
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ShareSuiteMapTransitionInternal()
		{
			MoneySharingHooks.MapTransitionActive = true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static DifficultyIndex FindR2APIDifficultyIndex(string nameToken)
		{
			//IL_001f: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			foreach (var (result, val3) in DifficultyAPI.difficultyDefinitions)
			{
				if (val3.nameToken == nameToken)
				{
					return result;
				}
			}
			return (DifficultyIndex)(-1);
		}
	}
	[BepInPlugin("com.Jaosnake.CENI", "C.E.N.I", "1.0.0")]
	public class ProperSavePlugin : BaseUnityPlugin
	{
		public const string GUID = "com.Jaosnake.CENI";

		public const string Name = "C.E.N.I";

		public const string Version = "1.0.0";

		internal const int MaxSaveSlotsPerCharacter = 5;

		private static readonly char[] invalidSubDirectoryCharacters = new char[3] { '\\', '/', '.' };

		internal static ProperSavePlugin Instance { get; private set; }

		internal static ManualLogSource InstanceLogger
		{
			get
			{
				ProperSavePlugin instance = Instance;
				if (instance == null)
				{
					return null;
				}
				return ((BaseUnityPlugin)instance).Logger;
			}
		}

		internal static FileSystem SavesFileSystem { get; private set; }

		internal static UPath SavesPath { get; private set; } = UPath.op_Implicit("/ProperSave") / UPath.op_Implicit("Saves");

		private static string SavesDirectory { get; set; }

		internal static SaveFileMetadata CurrentSave { get; set; }

		internal static string ContentHash { get; private set; }

		internal static ConfigEntry<bool> UseCloudStorage { get; private set; }

		internal static ConfigEntry<string> CloudStorageSubDirectory { get; private set; }

		internal static ConfigEntry<string> UserSavesDirectory { get; private set; }

		internal static ConfigEntry<bool> Resilient { get; private set; }

		private void Start()
		{
			Instance = this;
			UseCloudStorage = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "UseCloudStorage", false, "Store files in Steam/EpicGames cloud. Enabling this feature would not preserve current saves and disabling it wouldn't clear the cloud.");
			CloudStorageSubDirectory = ((BaseUnityPlugin)this).Config.Bind<string>("Main", "CloudStorageSubDirectory", "", "Sub directory name for cloud storage. Changing it allows to use different save files for different mod profiles.");
			UserSavesDirectory = ((BaseUnityPlugin)this).Config.Bind<string>("Main", "SavesDirectory", "", "Directory where save files will be stored. \"ProperSave\" directory will be created in the directory you have specified. If the directory doesn't exist the default one will be used.");
			Resilient = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Resilient", true, "Save file type. True - entries from catalogs will be saved by name instead of index, which should have less issue on mod list change, but has bigger save file size. False - the old way, entries from catalogs are saved by index, which works for non-changing mod list, save file size is much lower.");
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate
			{
				InitSaveFileSystem();
				ProperSave.Old.SaveFileMetadata.MigrateAll();
				SaveFileMetadata.PopulateSavesMetadata();
			});
			ModCompat.GatherLoadedPlugins();
			ModCompat.RegisterHooks();
			Saving.RegisterHooks();
			Loading.RegisterHooks();
			LobbyUI.RegisterHooks();
			LostNetworkUser.Subscribe();
			Language.collectLanguageRootFolders += CollectLanguageRootFolders;
			ContentManager.onContentPacksAssigned += ContentManagerOnContentPacksAssigned;
		}

		private void InitSaveFileSystem()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			if (UseCloudStorage.Value)
			{
				SavesFileSystem = RoR2Application.cloudStorage;
				if (!string.IsNullOrWhiteSpace(CloudStorageSubDirectory.Value))
				{
					if (CloudStorageSubDirectory.Value.IndexOfAny(invalidSubDirectoryCharacters) != -1)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)"Config entry \"CloudStorageSubDirectory\" contains invalid characters. Falling back to default location.");
					}
					else
					{
						SavesPath /= UPath.op_Implicit(CloudStorageSubDirectory.Value);
					}
				}
				return;
			}
			if (!string.IsNullOrWhiteSpace(UserSavesDirectory.Value))
			{
				if (!Directory.Exists(UserSavesDirectory.Value))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"SavesDirectory from the config doesn't exists, using Application.persistentDataPath");
					SavesDirectory = Application.persistentDataPath;
				}
				else
				{
					SavesDirectory = UserSavesDirectory.Value;
				}
			}
			else
			{
				SavesDirectory = Application.persistentDataPath;
			}
			if (string.IsNullOrWhiteSpace(SavesDirectory))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Application.persistentDataPath is empty. Use SavesDirectory config option to specify a folder.");
			}
			PhysicalFileSystem val = new PhysicalFileSystem();
			SavesFileSystem = (FileSystem)new SubFileSystem((IFileSystem)(object)val, ((FileSystem)val).ConvertPathFromInternal(SavesDirectory), true);
		}

		private void Destroy()
		{
			Instance = null;
			ModCompat.UnregisterHooks();
			Saving.UnregisterHooks();
			Loading.UnregisterHooks();
			LobbyUI.UnregisterHooks();
			LostNetworkUser.Unsubscribe();
			Language.collectLanguageRootFolders -= CollectLanguageRootFolders;
			ContentManager.onContentPacksAssigned -= ContentManagerOnContentPacksAssigned;
		}

		public void CollectLanguageRootFolders(List<string> folders)
		{
			folders.Add(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Language"));
		}

		private void ContentManagerOnContentPacksAssigned(ReadOnlyArray<ReadOnlyContentPack> contentPacks)
		{
			//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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			MD5 mD = MD5.Create();
			StringWriter writer = new StringWriter();
			try
			{
				Enumerator<ReadOnlyContentPack> enumerator = contentPacks.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ReadOnlyContentPack current = enumerator.Current;
						writer.Write(((ReadOnlyContentPack)(ref current)).identifier);
						writer.Write(';');
						WriteCollection<ArtifactDef>(((ReadOnlyContentPack)(ref current)).artifactDefs, "artifactDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).bodyPrefabs, "bodyPrefabs");
						WriteCollection<EquipmentDef>(((ReadOnlyContentPack)(ref current)).equipmentDefs, "equipmentDefs");
						WriteCollection<DroneDef>(((ReadOnlyContentPack)(ref current)).droneDefs, "droneDefs");
						WriteCollection<ExpansionDef>(((ReadOnlyContentPack)(ref current)).expansionDefs, "expansionDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).gameModePrefabs, "gameModePrefabs");
						WriteCollection<ItemDef>(((ReadOnlyContentPack)(ref current)).itemDefs, "itemDefs");
						WriteCollection<ItemTierDef>(((ReadOnlyContentPack)(ref current)).itemTierDefs, "itemTierDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).masterPrefabs, "masterPrefabs");
						WriteCollection<SceneDef>(((ReadOnlyContentPack)(ref current)).sceneDefs, "sceneDefs");
						WriteCollection<SkillDef>(((ReadOnlyContentPack)(ref current)).skillDefs, "skillDefs");
						WriteCollection<SkillFamily>(((ReadOnlyContentPack)(ref current)).skillFamilies, "skillFamilies");
						WriteCollection<SurvivorDef>(((ReadOnlyContentPack)(ref current)).survivorDefs, "survivorDefs");
						WriteCollection<UnlockableDef>(((ReadOnlyContentPack)(ref current)).unlockableDefs, "unlockableDefs");
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				ContentHash = Convert.ToBase64String(mD.ComputeHash(Encoding.UTF8.GetBytes(writer.ToString())));
			}
			finally
			{
				if (writer != null)
				{
					((IDisposable)writer).Dispose();
				}
			}
			void WriteCollection<T>(ReadOnlyNamedAssetCollection<T> collection, string collectionName)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				writer.Write(collectionName);
				int num = 0;
				AssetEnumerator<T> enumerator2 = collection.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						T current2 = enumerator2.Current;
						writer.Write(num);
						writer.Write('_');
						writer.Write(collection.GetAssetName(current2) ?? string.Empty);
						writer.Write(';');
						num++;
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
		}
	}
	public class SaveFile
	{
		internal static readonly int currentVersion = 1;

		public ProperSave.SaveData.RunData RunData { get; set; }

		public ProperSave.SaveData.TeamData TeamData { get; set; }

		public ProperSave.SaveData.RunArtifactsData RunArtifactsData { get; set; }

		public ProperSave.SaveData.ArtifactsData ArtifactsData { get; set; }

		public List<ProperSave.SaveData.PlayerData> PlayersData { get; set; } = new List<ProperSave.SaveData.PlayerData>();

		public Dictionary<string, ProperSave.Data.ModdedData> ModdedData { get; set; } = new Dictionary<string, ProperSave.Data.ModdedData>();

		public static event Action<Dictionary<string, object>> OnGatherSaveData;

		internal SaveFile()
		{
		}

		internal void FillFromCurrentRun()
		{
			RunData = ProperSave.SaveData.RunData.Create();
			TeamData = ProperSave.SaveData.TeamData.Create();
			RunArtifactsData = ProperSave.SaveData.RunArtifactsData.Create();
			ArtifactsData = ProperSave.SaveData.ArtifactsData.Create();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				LostNetworkUser lostUser = null;
				if (Object.op_Implicit((Object)(object)instance.networkUser) || LostNetworkUser.TryGetUser(instance.master, out lostUser))
				{
					PlayersData.Add(ProperSave.SaveData.PlayerData.Create(instance, lostUser));
				}
			}
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			Delegate[] array = SaveFile.OnGatherSaveData?.GetInvocationList();
			if (array != null)
			{
				Delegate[] array2 = array;
				foreach (Delegate obj in array2)
				{
					try
					{
						((Action<Dictionary<string, object>>)obj)(dictionary);
					}
					catch (Exception ex)
					{
						ProperSavePlugin.InstanceLogger.LogError((object)ex);
					}
				}
			}
			ModdedData = dictionary.ToDictionary((KeyValuePair<string, object> el) => el.Key, (KeyValuePair<string, object> el) => new ProperSave.Data.ModdedData
			{
				ObjectType = el.Value.GetType().AssemblyQualifiedName,
				Value = el.Value
			});
		}

		internal void LoadRun()
		{
			try
			{
				LegacyResourcesAPI.Load<GameObject>("Prefabs/PositionIndicators/TeleporterChargingPositionIndicator", true);
			}
			catch
			{
			}
			RunData.LoadData();
		}

		internal void LoadArtifacts()
		{
			RunArtifactsData.LoadData();
			ArtifactsData.LoadData();
		}

		internal void LoadTeam()
		{
			TeamData.LoadData();
		}

		internal void LoadPlayers()
		{
			if (NetworkUser.readOnlyInstancesList.Count == 1)
			{
				ProperSave.SaveData.PlayerData playerData = PlayersData.FirstOrDefault();
				if (playerData != null)
				{
					NetworkUser player = NetworkUser.readOnlyInstancesList.FirstOrDefault();
					playerData.LoadPlayer(player);
				}
				return;
			}
			List<ProperSave.SaveData.PlayerData> list = PlayersData.ToList();
			foreach (NetworkUser user in NetworkUser.readOnlyInstancesList)
			{
				ProperSave.SaveData.PlayerData playerData2 = list.FirstOrDefault(delegate(ProperSave.SaveData.PlayerData el)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					NetworkUserId val = el.userId.Load();
					return ((NetworkUserId)(ref val)).Equals(user.id);
				});
				if (playerData2 != null)
				{
					list.Remove(playerData2);
					playerData2.LoadPlayer(user);
				}
			}
		}

		public T GetModdedData<T>(string key)
		{
			return (T)ModdedData[key].Value;
		}

		internal static SaveFile Read(BinaryReader reader)
		{
			SaveFile saveFile = new SaveFile();
			int version = reader.ReadInt32();
			bool resilient = reader.ReadBoolean();
			long offset = reader.ReadInt64();
			long position = reader.BaseStream.Position;
			reader.BaseStream.Seek(offset, SeekOrigin.Begin);
			string[] array = new string[reader.ReadInt32()];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = reader.ReadString();
			}
			long position2 = reader.BaseStream.Position;
			reader.BaseStream.Seek(position, SeekOrigin.Begin);
			ReaderContext context = new ReaderContext
			{
				Reader = reader,
				Resilient = resilient,
				SharedStrings = array,
				Version = version
			};
			saveFile.ArtifactsData = ProperSave.SaveData.ArtifactsData.Read(context);
			saveFile.RunData = ProperSave.SaveData.RunData.Read(context);
			saveFile.RunArtifactsData = ProperSave.SaveData.RunArtifactsData.Read(context);
			saveFile.TeamData = ProperSave.SaveData.TeamData.Read(context);
			int num = reader.ReadInt32();
			for (int j = 0; j < num; j++)
			{
				saveFile.PlayersData.Add(ProperSave.SaveData.PlayerData.Read(context));
			}
			saveFile.ModdedData = ReadModdedData(context);
			reader.BaseStream.Seek(position2, SeekOrigin.Begin);
			return saveFile;
		}

		private static Dictionary<string, ProperSave.Data.ModdedData> ReadModdedData(ReaderContext context)
		{
			return context.Reader.ReadString().FromJson<Dictionary<string, ProperSave.Data.ModdedData>>();
		}

		internal void Write(BinaryWriter writer, bool resilient)
		{
			WriterContext writerContext = new WriterContext
			{
				Writer = writer,
				SharedStrings = new List<string>(),
				Resilient = resilient
			};
			writer.Write(currentVersion);
			writer.Write(resilient);
			long position = writer.BaseStream.Position;
			writer.Write(0L);
			ArtifactsData.Write(writerContext);
			RunData.Write(writerContext);
			RunArtifactsData.Write(writerContext);
			TeamData.Write(writerContext);
			writer.Write(PlayersData.Count);
			for (int i = 0; i < PlayersData.Count; i++)
			{
				PlayersData[i].Write(writerContext);
			}
			WriteModdedData(writerContext);
			long position2 = writer.BaseStream.Position;
			writer.Write(writerContext.SharedStrings.Count);
			for (int j = 0; j < writerContext.SharedStrings.Count; j++)
			{
				writer.Write(writerContext.SharedStrings[j]);
			}
			writer.BaseStream.Seek(position, SeekOrigin.Begin);
			writer.Write(position2);
			writer.BaseStream.Seek(writer.BaseStream.Length, SeekOrigin.Begin);
		}

		private void WriteModdedData(WriterContext context)
		{
			context.Writer.Write(ModdedData.ToJson());
		}
	}
	public class SaveFileHeader
	{
		internal static readonly int currentVersion = 1;

		public DateTime SaveDate { get; internal set; }

		public string UserProfileId { get; internal set; }

		public HeaderUserData[] Users { get; internal set; }

		public GameModeIndex GameMode { get; internal set; }

		public string SceneName { get; internal set; }

		public DifficultyIndex Difficulty { get; internal set; }

		public int Time { get; internal set; }

		public int StageClearCount { get; internal set; }

		public string ContentHash { get; internal set; }

		public void FillFromCurrentRun()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			Users = (from el in PlayerCharacterMasterController.instances.Select(HeaderUserData.Create)
				where el != null
				select el).ToArray();
			UserProfileId = LocalUserManager.readOnlyLocalUsersList[0].userProfile.fileName;
			GameMode = Run.instance.gameModeIndex;
			ContentHash = ProperSavePlugin.ContentHash;
			Difficulty = Run.instance.selectedDifficulty;
			Scene activeScene = SceneManager.GetActiveScene();
			SceneName = ((Scene)(ref activeScene)).name;
			StageClearCount = Run.instance.stageClearCount;
			RunStopwatch runStopwatch = Run.instance.runStopwatch;
			Time = (runStopwatch.isPaused ? ((int)runStopwatch.offsetFromFixedTime) : ((int)(Run.instance.fixedTime + runStopwatch.offsetFromFixedTime)));
		}

		internal static SaveFileHeader Read(BinaryReader reader)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			SaveFileHeader saveFileHeader = new SaveFileHeader();
			int version = reader.ReadInt32();
			bool resilient = reader.ReadBoolean();
			long offset = reader.ReadInt64();
			long position = reader.BaseStream.Position;
			reader.BaseStream.Seek(offset, SeekOrigin.Begin);
			string[] array = new string[reader.ReadInt32()];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = reader.ReadString();
			}
			long position2 = reader.BaseStream.Position;
			reader.BaseStream.Seek(position, SeekOrigin.Begin);
			ReaderContext context = new ReaderContext
			{
				Reader = reader,
				Resilient = resilient,
				SharedStrings = array,
				Version = version
			};
			saveFileHeader.SaveDate = new DateTime(reader.ReadInt64(), DateTimeKind.Utc);
			saveFileHeader.UserProfileId = reader.ReadString();
			saveFileHeader.Users = new HeaderUserData[reader.ReadInt32()];
			for (int j = 0; j < saveFileHeader.Users.Length; j++)
			{
				saveFileHeader.Users[j] = HeaderUserData.Read(context);
			}
			saveFileHeader.GameMode = SharedIndexHelpers.ResolveGameMode(reader.ReadInt32(), context);
			saveFileHeader.SceneName = reader.ReadString();
			saveFileHeader.Difficulty = SharedIndexHelpers.ResolveDifficulty(reader.ReadInt32(), context);
			saveFileHeader.Time = reader.ReadInt32();
			saveFileHeader.StageClearCount = reader.ReadInt32();
			saveFileHeader.ContentHash = reader.ReadString();
			reader.BaseStream.Seek(position2, SeekOrigin.Begin);
			return saveFileHeader;
		}

		internal void Write(BinaryWriter writer, bool resilient)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			WriterContext writerContext = new WriterContext
			{
				Writer = writer,
				SharedStrings = new List<string>(),
				Resilient = resilient
			};
			writer.Write(currentVersion);
			writer.Write(resilient);
			long position = writer.BaseStream.Position;
			writer.Write(0L);
			writer.Write(DateTime.UtcNow.Ticks);
			writer.Write(UserProfileId);
			writer.Write(Users.Length);
			for (int i = 0; i < Users.Length; i++)
			{
				Users[i].Write(writerContext);
			}
			writer.Write(SharedIndexHelpers.FromGameMode(GameMode, writerContext));
			writer.Write(SceneName);
			writer.Write(SharedIndexHelpers.FromDifficulty(Difficulty, writerContext));
			writer.Write(Time);
			writer.Write(StageClearCount);
			writer.Write(ContentHash);
			long position2 = writer.BaseStream.Position;
			writer.Write(writerContext.SharedStrings.Count);
			for (int j = 0; j < writerContext.SharedStrings.Count; j++)
			{
				writer.Write(writerContext.SharedStrings[j]);
			}
			writer.BaseStream.Seek(position, SeekOrigin.Begin);
			writer.Write(position2);
			writer.BaseStream.Seek(writer.BaseStream.Length, SeekOrigin.Begin);
		}
	}
	public class SaveFileMetadata
	{
		public string FileName { get; internal set; }

		public bool ForceLoad { get; internal set; }

		public SaveFileHeader Header { get; internal set; }

		public long BodyOffset { get; internal set; }

		public SaveFile Body { get; internal set; }

		public UPath? FilePath => string.IsNullOrEmpty(FileName) ? UPath.op_Implicit((string)null) : (ProperSavePlugin.SavesPath / UPath.op_Implicit(FileName + ".bin"));

		internal static List<SaveFileMetadata> SavesMetadata { get; } = new List<SaveFileMetadata>();

		internal void FillMetadataForCurrentLobby()
		{
			//IL_006a: Unknown res