Decompiled source of ProperSave v2.11.2

plugins/ProperSave/ProperSave.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
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 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.SaveData;
using ProperSave.SaveData.Artifacts;
using ProperSave.SaveData.Runs;
using ProperSave.TinyJson;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.11.2.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;
				}
			}
			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 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 class Loading
	{
		private static bool isLoading;

		public static bool IsLoading
		{
			get
			{
				return isLoading;
			}
			private 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;

		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)
			{
				ProperSavePlugin.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)
				{
					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()
		{
			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;
			}
			SaveFileMetadata currentLobbySaveMetadata = SaveFileMetadata.GetCurrentLobbySaveMetadata();
			if (currentLobbySaveMetadata == null)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Save file for current users is not found");
				yield break;
			}
			UPath? filePath = currentLobbySaveMetadata.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;
			}
			ProperSavePlugin.CurrentSave = FileSystemExtensions.ReadAllText((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, filePath.Value).FromJson<SaveFile>();
			ProperSavePlugin.CurrentSave.SaveFileMeta = currentLobbySaveMetadata;
			IsLoading = true;
			if (ProperSavePlugin.CurrentSave.ContentHash != null && ProperSavePlugin.CurrentSave.ContentHash != ProperSavePlugin.ContentHash)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Loading run but content mismatch detected which may result in errors");
			}
			PreGameController.instance.StartRun();
		}
	}
	internal static class LobbyUI
	{
		private static GameObject lobbyButton;

		private static GameObject lobbySubmenuLegend;

		private static GameObject lobbyGlyphAndDescription;

		private static TooltipProvider tooltipProvider;

		private static GamepadTooltipProvider gamepadTooltipProvider;

		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 = "[ProperSave] 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 = "[ProperSave] 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");
			}
			else if (Loading.IsLoading)
			{
				ProperSavePlugin.InstanceLogger.LogInfo((object)"Already loading");
			}
			else
			{
				((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(Loading.LoadLobby());
			}
		}

		private static void UpdateLobbyControls(NetworkUser exceptUser = null)
		{
			//IL_004e: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_0156: 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);
			TooltipContent content = default(TooltipContent);
			try
			{
				if (currentLobbySaveMetadata != null)
				{
					TooltipContent val = default(TooltipContent);
					val.titleToken = LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_TITLE;
					val.overrideBodyText = GetSaveDescription(currentLobbySaveMetadata);
					val.titleColor = Color.black;
					val.disableBodyRichText = false;
					content = val;
				}
			}
			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(content);
				}
			}
			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(content);
				}
			}
			catch
			{
			}
		}

		private static string GetSaveDescription(SaveFileMetadata saveMetadata)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			SaveFile saveFile = FileSystemExtensions.ReadAllText((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, saveMetadata.FilePath.Value).FromJson<SaveFile>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (PlayerData playerData in saveFile.PlayersData)
			{
				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 = playerData.userId.Load();
					return ((NetworkUserId)(ref val3)).Equals(user.id);
				});
				SurvivorDef val2 = SurvivorCatalog.FindSurvivorDefFromBody(BodyCatalog.FindBodyPrefab(playerData.master.bodyName));
				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(saveFile.RunData.sceneName);
			DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef((DifficultyIndex)saveFile.RunData.difficulty);
			int num = (saveFile.RunData.isPaused ? ((int)saveFile.RunData.offsetFromFixedTime) : ((int)(saveFile.RunData.fixedTime + saveFile.RunData.offsetFromFixedTime)));
			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) : "",
				(saveFile.RunData.stageClearCount + 1).ToString(),
				$"{num / 60:00}:{num % 60:00}",
				(difficultyDef != null) ? Language.GetString(difficultyDef.nameToken) : "",
				(saveFile.ContentHash != null && saveFile.ContentHash != ProperSavePlugin.ContentHash) ? Language.GetString(LanguageConsts.PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH) : ""
			});
		}
	}
	internal class LostNetworkUser : MonoBehaviour
	{
		private static readonly Dictionary<CharacterMaster, LostNetworkUser> lostUsers = new Dictionary<CharacterMaster, LostNetworkUser>();

		private CharacterMaster master;

		public uint lunarCoins;

		public NetworkUserId userID;

		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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)networkUser.master))
			{
				LostNetworkUser lostNetworkUser = ((Component)networkUser.master).gameObject.AddComponent<LostNetworkUser>();
				lostNetworkUser.lunarCoins = networkUser.lunarCoins;
				lostNetworkUser.userID = networkUser.id;
			}
		}
	}
	internal static class ModSupport
	{
		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; }

		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");
		}

		public static void RegisterHooks()
		{
			if (IsBBLoaded = Chainloader.PluginInfos.ContainsKey("com.MagnusMagnuson.BiggerBazaar"))
			{
				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)
		{
			if (IsSSLoaded)
			{
				((MonoBehaviour)ProperSavePlugin.Instance).StartCoroutine(LoadShareSuiteMoneyInternal(money));
			}
		}

		[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()
		{
			if (IsSSLoaded)
			{
				ShareSuiteMapTransionInternal();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ShareSuiteMapTransionInternal()
		{
			MoneySharingHooks.MapTransitionActive = true;
		}
	}
	[BepInPlugin("com.KingEnderBrine.ProperSave", "Proper Save", "2.11.2")]
	public class ProperSavePlugin : BaseUnityPlugin
	{
		public const string GUID = "com.KingEnderBrine.ProperSave";

		public const string Name = "Proper Save";

		public const string Version = "2.11.2";

		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 SaveFile 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; }

		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.");
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate
			{
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Expected O, but got Unknown
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: 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);
						}
					}
				}
				else
				{
					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);
				}
				SaveFileMetadata.PopulateSavesMetadata();
			});
			ModSupport.GatherLoadedPlugins();
			ModSupport.RegisterHooks();
			Saving.RegisterHooks();
			Loading.RegisterHooks();
			LobbyUI.RegisterHooks();
			LostNetworkUser.Subscribe();
			Language.collectLanguageRootFolders += CollectLanguageRootFolders;
			ContentManager.onContentPacksAssigned += ContentManagerOnContentPacksAssigned;
		}

		private void Destroy()
		{
			Instance = null;
			ModSupport.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)
			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<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).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).Dispose();
				}
			}
		}
	}
	public class SaveFile
	{
		[DataMember(Name = "r")]
		public RunData RunData { get; set; }

		[DataMember(Name = "t")]
		public TeamData TeamData { get; set; }

		[DataMember(Name = "ra")]
		public RunArtifactsData RunArtifactsData { get; set; }

		[DataMember(Name = "a")]
		public ArtifactsData ArtifactsData { get; set; }

		[DataMember(Name = "p")]
		public List<PlayerData> PlayersData { get; set; }

		[DataMember(Name = "md")]
		public Dictionary<string, ModdedData> ModdedData { get; set; }

		[DataMember(Name = "ch")]
		public string ContentHash { get; set; }

		[IgnoreDataMember]
		public SaveFileMetadata SaveFileMeta { get; set; }

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

		[EditorBrowsable(EditorBrowsableState.Never)]
		[Obsolete("Use OnGatherSaveData without a typo", true)]
		public static event Action<Dictionary<string, object>> OnGatgherSaveData
		{
			add
			{
				OnGatherSaveData += value;
			}
			remove
			{
				OnGatherSaveData -= value;
			}
		}

		internal SaveFile()
		{
			RunData = new RunData();
			TeamData = new TeamData();
			RunArtifactsData = new RunArtifactsData();
			ArtifactsData = new ArtifactsData();
			PlayersData = new List<PlayerData>();
			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(new PlayerData(instance, lostUser));
				}
			}
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			SaveFile.OnGatherSaveData?.Invoke(dictionary);
			ModdedData = dictionary.ToDictionary((KeyValuePair<string, object> el) => el.Key, (KeyValuePair<string, object> el) => new ModdedData
			{
				ObjectType = el.Value.GetType().AssemblyQualifiedName,
				Value = el.Value
			});
			ContentHash = ProperSavePlugin.ContentHash;
		}

		internal void LoadRun()
		{
			RunData.LoadData();
		}

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

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

		internal void LoadPlayers()
		{
			List<PlayerData> list = PlayersData.ToList();
			foreach (NetworkUser user in NetworkUser.readOnlyInstancesList)
			{
				PlayerData playerData = list.FirstOrDefault(delegate(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 (playerData != null)
				{
					list.Remove(playerData);
					playerData.LoadPlayer(user);
				}
			}
		}

		public T GetModdedData<T>(string key)
		{
			return (T)ModdedData[key].Value;
		}
	}
	public class SaveFileMetadata
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass22_0
		{
			public List<NetworkUserId> users;

			public GameModeIndex gameMode;

			internal bool <GetCurrentLobbySaveMetadata>b__1(SaveFileMetadata el)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (el.UserIds.Length != users.Count || el.GameMode != gameMode)
				{
					return false;
				}
				return users.DifferenceCount(el.UserIds.Select((UserIDData e) => (NetworkUserId)(((??)e?.Load()) ?? default(NetworkUserId)))) == 0;
			}
		}

		[DataMember(Name = "fn")]
		public string FileName { get; set; }

		[DataMember(Name = "upi")]
		public string UserProfileId { get; set; }

		[DataMember(Name = "si")]
		public UserIDData[] UserIds { get; set; }

		[DataMember(Name = "gm")]
		public GameModeIndex GameMode { get; set; }

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

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


		internal static SaveFileMetadata CreateMetadataForCurrentLobby()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			LostNetworkUser lostUser;
			return new SaveFileMetadata
			{
				UserIds = (from el in PlayerCharacterMasterController.instances
					select (!Object.op_Implicit((Object)(object)el.networkUser)) ? ((!LostNetworkUser.TryGetUser(el.master, out lostUser)) ? null : new UserIDData(lostUser.userID)) : new UserIDData(el.networkUser.id) into el
					where el != null
					select el).ToArray(),
				UserProfileId = LocalUserManager.readOnlyLocalUsersList[0].userProfile.fileName,
				GameMode = Run.instance.gameModeIndex
			};
		}

		internal static SaveFileMetadata GetCurrentLobbySaveMetadata(NetworkUser exceptUser = null)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Invalid comparison between Unknown and I4
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Invalid comparison between Unknown and I4
			//IL_009b->IL009b: Incompatible stack types: O vs I4
			//IL_0091->IL009b: Incompatible stack types: O vs I4
			//IL_0085->IL009b: Incompatible stack types: I4 vs O
			//IL_0085->IL009b: Incompatible stack types: O vs I4
			try
			{
				<>c__DisplayClass22_0 CS$<>8__locals0 = new <>c__DisplayClass22_0();
				CS$<>8__locals0.users = NetworkUser.readOnlyInstancesList.Select((NetworkUser el) => el.id).ToList();
				if ((Object)(object)exceptUser != (Object)null)
				{
					CS$<>8__locals0.users.Remove(exceptUser.id);
				}
				if (CS$<>8__locals0.users.Count == 0)
				{
					return null;
				}
				object obj = CS$<>8__locals0;
				int num;
				if (Object.op_Implicit((Object)(object)PreGameController.instance))
				{
					obj = PreGameController.instance.gameModeIndex;
					num = (int)obj;
				}
				else if (Object.op_Implicit((Object)(object)Run.instance))
				{
					obj = Run.instance.gameModeIndex;
					num = (int)obj;
				}
				else
				{
					num = -1;
					obj = num;
					num = (int)obj;
				}
				((<>c__DisplayClass22_0)num).gameMode = (GameModeIndex)obj;
				if ((int)CS$<>8__locals0.gameMode == -1)
				{
					return null;
				}
				if (CS$<>8__locals0.users.Count == 1)
				{
					<>c__DisplayClass22_0 <>c__DisplayClass22_ = CS$<>8__locals0;
					string profile = LocalUserManager.readOnlyLocalUsersList[0].userProfile.fileName.Replace(".xml", "");
					return SavesMetadata.FirstOrDefault(delegate(SaveFileMetadata el)
					{
						//IL_002d: Unknown result type (might be due to invalid IL or missing references)
						//IL_0032: Unknown result type (might be due to invalid IL or missing references)
						//IL_0041: 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_0059: Unknown result type (might be due to invalid IL or missing references)
						if (el.UserProfileId == profile && el.UserIds.Length == 1)
						{
							UserIDData obj2 = el.UserIds[0];
							if (obj2 != null)
							{
								NetworkUserId val = obj2.Load();
								if (((NetworkUserId)(ref val)).Equals(<>c__DisplayClass22_.users[0]))
								{
									return el.GameMode == <>c__DisplayClass22_.gameMode;
								}
							}
						}
						return false;
					});
				}
				return SavesMetadata.FirstOrDefault((SaveFileMetadata el) => el.UserIds.Length == CS$<>8__locals0.users.Count && el.GameMode == CS$<>8__locals0.gameMode && CS$<>8__locals0.users.DifferenceCount(el.UserIds.Select((UserIDData e) => (NetworkUserId)(((??)e?.Load()) ?? default(NetworkUserId)))) == 0);
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Couldn't get save metadata for current lobby");
				ProperSavePlugin.InstanceLogger.LogError((object)ex.ToString());
				return null;
			}
		}

		internal static void PopulateSavesMetadata()
		{
			//IL_0005: 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_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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			if (!ProperSavePlugin.SavesFileSystem.DirectoryExists(ProperSavePlugin.SavesPath))
			{
				ProperSavePlugin.SavesFileSystem.CreateDirectory(ProperSavePlugin.SavesPath);
				return;
			}
			UPath val = ProperSavePlugin.SavesPath / UPath.op_Implicit("SavesMetadata.json");
			if (!ProperSavePlugin.SavesFileSystem.FileExists(val))
			{
				return;
			}
			try
			{
				SaveFileMetadata[] collection = FileSystemExtensions.ReadAllText((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, val).FromJson<SaveFileMetadata[]>();
				SavesMetadata.Clear();
				SavesMetadata.AddRange(collection);
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"SavesMetadata file corrupted.");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		internal static void AddIfNotExists(SaveFileMetadata metadata)
		{
			if (!SavesMetadata.Contains(metadata))
			{
				SavesMetadata.Add(metadata);
				UpdateSaveMetadata();
			}
		}

		internal static void Remove(SaveFileMetadata metadata)
		{
			if (SavesMetadata.Remove(metadata))
			{
				UpdateSaveMetadata();
			}
		}

		private static void UpdateSaveMetadata()
		{
			//IL_0005: 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_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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!ProperSavePlugin.SavesFileSystem.DirectoryExists(ProperSavePlugin.SavesPath))
			{
				ProperSavePlugin.SavesFileSystem.CreateDirectory(ProperSavePlugin.SavesPath);
				return;
			}
			UPath val = ProperSavePlugin.SavesPath / UPath.op_Implicit("SavesMetadata.json");
			try
			{
				FileSystemExtensions.WriteAllText((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, val, SavesMetadata.ToJson());
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Can't update SavesMetadata file");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}
	}
	internal static class Saving
	{
		internal static RunRngData PreStageRng { get; private set; }

		internal static RngData PreStageInfiniteTowerSafeWardRng { get; private set; }

		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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			Run.BeginStage += new hook_BeginStage(StageOnStageStartGlobal);
			Run.onServerGameOver += RunOnServerGameOver;
			Run.GenerateStageRNG += new hook_GenerateStageRNG(RunGenerateStageRNG);
			QuitConfirmationHelper.IssueQuitCommand_Action += new Manipulator(IssueQuitCommandIL);
		}

		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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			Run.BeginStage -= new hook_BeginStage(StageOnStageStartGlobal);
			Run.onServerGameOver -= RunOnServerGameOver;
			Run.GenerateStageRNG -= new hook_GenerateStageRNG(RunGenerateStageRNG);
			QuitConfirmationHelper.IssueQuitCommand_Action -= new Manipulator(IssueQuitCommandIL);
		}

		private static void RunGenerateStageRNG(orig_GenerateStageRNG orig, Run self)
		{
			PreStageRng = new RunRngData(Run.instance);
			InfiniteTowerRun val = (InfiniteTowerRun)(object)((self is InfiniteTowerRun) ? self : null);
			if (val != null)
			{
				PreStageInfiniteTowerSafeWardRng = new RngData(val.safeWardRng);
			}
			orig.Invoke(self);
		}

		private static void RunOnServerGameOver(Run run, GameEndingDef ending)
		{
			//IL_0033: 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)
			try
			{
				SaveFileMetadata saveFileMetadata = ProperSavePlugin.CurrentSave?.SaveFileMeta;
				if (saveFileMetadata != null && saveFileMetadata.FilePath.HasValue)
				{
					if (ProperSavePlugin.SavesFileSystem.FileExists(saveFileMetadata.FilePath.Value))
					{
						ProperSavePlugin.SavesFileSystem.DeleteFile(saveFileMetadata.FilePath.Value);
					}
					SaveFileMetadata.Remove(saveFileMetadata);
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to delete save file");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		private static void StageOnStageStartGlobal(orig_BeginStage orig, Run self)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			try
			{
				if (!NetworkServer.active)
				{
					return;
				}
				if (Loading.FirstRunStage)
				{
					Loading.FirstRunStage = false;
					return;
				}
				SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene();
				if ((int)sceneDefForCurrentScene.sceneType != 0 && (int)sceneDefForCurrentScene.sceneType != 3)
				{
					SaveGame();
				}
			}
			finally
			{
				orig.Invoke(self);
			}
		}

		private static void SaveGame()
		{
			//IL_005e: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			SaveFile saveFile = new SaveFile
			{
				SaveFileMeta = (SaveFileMetadata.GetCurrentLobbySaveMetadata() ?? SaveFileMetadata.CreateMetadataForCurrentLobby())
			};
			if (string.IsNullOrEmpty(saveFile.SaveFileMeta.FileName))
			{
				do
				{
					saveFile.SaveFileMeta.FileName = Guid.NewGuid().ToString();
				}
				while (ProperSavePlugin.SavesFileSystem.FileExists(saveFile.SaveFileMeta.FilePath.Value));
			}
			try
			{
				string text = saveFile.ToJson();
				FileSystemExtensions.WriteAllText((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, saveFile.SaveFileMeta.FilePath.Value, text);
				ProperSavePlugin.CurrentSave = saveFile;
				SaveFileMetadata.AddIfNotExists(saveFile.SaveFileMeta);
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = string.Format(Language.GetString(LanguageConsts.PROPER_SAVE_CHAT_SAVE), Language.GetString(SceneCatalog.currentSceneDef.nameToken))
				});
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)"Failed to save the game");
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
		}

		private static void IssueQuitCommandIL(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			MethodReference val3 = default(MethodReference);
			MethodReference val2 = default(MethodReference);
			string text = default(string);
			val.GotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdftn(x, ref val3),
				(Instruction x) => ILPatternMatchingExt.MatchNewobj(x, ref val2),
				(Instruction x) => ILPatternMatchingExt.MatchLdstr(x, ref text)
			});
			val.Emit(OpCodes.Dup);
			val.EmitDelegate<Action<SimpleDialogBox>>((Action<SimpleDialogBox>)AddQuitText);
		}

		private static void AddQuitText(SimpleDialogBox simpleDialogBox)
		{
			if (NetworkServer.active || NetworkUser.readOnlyInstancesList.Count == NetworkUser.readOnlyLocalPlayersList.Count)
			{
				if (ProperSavePlugin.CurrentSave == null)
				{
					TextMeshProUGUI descriptionLabel = simpleDialogBox.descriptionLabel;
					((TMP_Text)descriptionLabel).text = ((TMP_Text)descriptionLabel).text + Language.GetString(LanguageConsts.PROPER_SAVE_QUIT_DIALOG_NOT_SAVED);
					return;
				}
				if (ProperSavePlugin.CurrentSave.RunData.stageClearCount == Run.instance.stageClearCount)
				{
					TextMeshProUGUI descriptionLabel2 = simpleDialogBox.descriptionLabel;
					((TMP_Text)descriptionLabel2).text = ((TMP_Text)descriptionLabel2).text + Language.GetString(LanguageConsts.PROPER_SAVE_QUIT_DIALOG_SAVED);
					return;
				}
				TextMeshProUGUI descriptionLabel3 = simpleDialogBox.descriptionLabel;
				string text = ((TMP_Text)descriptionLabel3).text;
				string pROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE = LanguageConsts.PROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE;
				object[] array = new string[1] { (Run.instance.stageClearCount - ProperSavePlugin.CurrentSave.RunData.stageClearCount).ToString() };
				((TMP_Text)descriptionLabel3).text = text + Language.GetStringFormatted(pROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE, array);
			}
		}
	}
}
namespace ProperSave.SaveData
{
	public class ArtifactsData
	{
		[DataMember(Name = "ed")]
		public EnigmaData EnigmaData;

		internal ArtifactsData()
		{
			EnigmaData = new EnigmaData();
		}

		internal void LoadData()
		{
			EnigmaData.LoadData();
		}
	}
	public class MinionData
	{
		[DataMember(Name = "mi")]
		public int masterIndex;

		[DataMember(Name = "m")]
		public CharacterMasterData master;

		[DataMember(Name = "dld")]
		public DevotedLemurianData devotedLemurianData;

		internal MinionData(CharacterMaster master)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			masterIndex = (int)master.masterIndex;
			this.master = new CharacterMasterData(master);
			DevotedLemurianController controller = default(DevotedLemurianController);
			if (((Component)master).TryGetComponent<DevotedLemurianController>(ref controller))
			{
				devotedLemurianData = new DevotedLemurianData(controller);
			}
		}

		internal void LoadMinion(CharacterMaster playerMaster)
		{
			SceneDirector.onPostPopulateSceneServer += SpawnMinion;
			void SpawnMinion(SceneDirector obj)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				SceneDirector.onPostPopulateSceneServer -= SpawnMinion;
				GameObject obj2 = Object.Instantiate<GameObject>(MasterCatalog.GetMasterPrefab((MasterIndex)masterIndex));
				CharacterMaster component = obj2.GetComponent<CharacterMaster>();
				component.teamIndex = (TeamIndex)1;
				master.LoadMaster(component, delayedInventory: true);
				CharacterMaster val = playerMaster;
				if ((Object)(object)val.minionOwnership.ownerMaster != (Object)null)
				{
					val = val.minionOwnership.ownerMaster;
				}
				component.minionOwnership.SetOwner(val);
				obj2.GetComponent<AIOwnership>().ownerMaster = playerMaster;
				obj2.GetComponent<BaseAI>().leader.gameObject = ((Component)playerMaster).gameObject;
				if (devotedLemurianData != null)
				{
					DevotedLemurianController component2 = ((Component)component).GetComponent<DevotedLemurianController>();
					devotedLemurianData.LoadData(component2);
					component2._lemurianMaster = component;
					component2._devotionInventoryController = CharacterMasterData.GetDevotionInventoryController(playerMaster);
				}
				NetworkServer.Spawn(obj2);
			}
		}
	}
	public class PlayerData
	{
		[DataMember(Name = "si")]
		public UserIDData userId;

		[DataMember(Name = "sf")]
		public string[] statsFields;

		[DataMember(Name = "su")]
		public int[] statsUnlockables;

		[DataMember(Name = "lc")]
		public uint lunarCoins;

		[DataMember(Name = "lccm")]
		public float lunarCoinChanceMultiplier;

		[DataMember(Name = "m")]
		public CharacterMasterData master;

		internal PlayerData(PlayerCharacterMasterController player, LostNetworkUser lostNetworkUser = null)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected I4, but got Unknown
			NetworkUser networkUser = player.networkUser;
			if ((Object)(object)lostNetworkUser != (Object)null)
			{
				userId = new UserIDData(lostNetworkUser.userID);
				lunarCoins = lostNetworkUser.lunarCoins;
			}
			else
			{
				userId = new UserIDData(networkUser.id);
				lunarCoins = networkUser.lunarCoins;
			}
			lunarCoinChanceMultiplier = player.lunarCoinChanceMultiplier;
			master = new CharacterMasterData(player.master);
			StatSheet currentStats = ((Component)player).GetComponent<PlayerStatsComponent>().currentStats;
			statsFields = new string[currentStats.fields.Length];
			for (int i = 0; i < currentStats.fields.Length; i++)
			{
				StatField val = currentStats.fields[i];
				statsFields[i] = ((object)(StatField)(ref val)).ToString();
			}
			statsUnlockables = new int[currentStats.GetUnlockableCount()];
			for (int j = 0; j < currentStats.GetUnlockableCount(); j++)
			{
				UnlockableIndex unlockableIndex = currentStats.GetUnlockableIndex(j);
				statsUnlockables[j] = (int)unlockableIndex;
			}
		}

		internal void LoadPlayer(NetworkUser player)
		{
			master.LoadMaster(player.master, delayedInventory: false);
			player.masterController.lunarCoinChanceMultiplier = lunarCoinChanceMultiplier;
			StatSheet currentStats = ((Component)player.masterController).GetComponent<PlayerStatsComponent>().currentStats;
			for (int i = 0; i < statsFields.Length; i++)
			{
				string text = statsFields[i];
				currentStats.SetStatValueFromString(StatDef.allStatDefs[i], text);
			}
			for (int j = 0; j < statsUnlockables.Length; j++)
			{
				int num = statsUnlockables[j];
				currentStats.AddUnlockable((UnlockableIndex)num);
			}
		}
	}
	public class RunArtifactsData
	{
		[DataMember(Name = "a")]
		public bool[] artifacts;

		internal RunArtifactsData()
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			artifacts = new bool[ArtifactCatalog.artifactCount];
			RunEnabledArtifacts enumerator = RunArtifactManager.enabledArtifactsEnumerable.GetEnumerator();
			try
			{
				while (((RunEnabledArtifacts)(ref enumerator)).MoveNext())
				{
					ArtifactDef current = ((RunEnabledArtifacts)(ref enumerator)).Current;
					artifacts[current.artifactIndex] = true;
				}
			}
			finally
			{
				((IDisposable)(RunEnabledArtifacts)(ref enumerator)).Dispose();
			}
			ArtifactTrialMissionController val = Object.FindObjectOfType<ArtifactTrialMissionController>();
			int num = val?.currentArtifactIndex ?? (-1);
			if (num != -1)
			{
				artifacts[num] = val.artifactWasEnabled;
			}
		}

		internal void LoadData()
		{
			for (int i = 0; i < ArtifactCatalog.artifactCount; i++)
			{
				ArtifactDef artifactDef = ArtifactCatalog.GetArtifactDef((ArtifactIndex)i);
				RunArtifactManager.instance.SetArtifactEnabled(artifactDef, artifacts.ElementAtOrDefault(i));
			}
		}
	}
	public class RunData
	{
		[DataMember(Name = "s")]
		public ulong seed;

		[DataMember(Name = "d")]
		public int difficulty;

		[DataMember(Name = "ft")]
		public float fixedTime;

		[DataMember(Name = "t")]
		public float time;

		[DataMember(Name = "ip")]
		public bool isPaused;

		[DataMember(Name = "offt")]
		public float offsetFromFixedTime;

		[DataMember(Name = "scc")]
		public int stageClearCount;

		[DataMember(Name = "sn")]
		public string sceneName;

		[DataMember(Name = "nsn")]
		public string nextSceneName;

		[DataMember(Name = "im")]
		public ItemMaskData itemMask;

		[DataMember(Name = "em")]
		public EquipmentMaskData equipmentMask;

		[DataMember(Name = "spc")]
		public int shopPortalCount;

		[DataMember(Name = "ef")]
		public string[] eventFlags;

		[DataMember(Name = "rr")]
		public RunRngData runRng;

		[DataMember(Name = "ta")]
		public int trialArtifact;

		[DataMember(Name = "rb")]
		public RuleBookData ruleBook;

		[DataMember(Name = "trdt")]
		public string typeRunDataType;

		[DataMember(Name = "trd")]
		[DiscoverObjectType("typeRunDataType")]
		public ITypedRunData typedRunData;

		private static readonly FieldInfo onRunStartGlobalDelegate = typeof(Run).GetField("onRunStartGlobal", BindingFlags.Static | BindingFlags.NonPublic);

		internal RunData()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected I4, but got Unknown
			//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_002c: 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_0068: 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)
			Run instance = Run.instance;
			seed = instance.seed;
			difficulty = (int)instance.selectedDifficulty;
			RunStopwatch runStopwatch = instance.runStopwatch;
			isPaused = runStopwatch.isPaused;
			offsetFromFixedTime = runStopwatch.offsetFromFixedTime;
			fixedTime = instance.fixedTime;
			time = instance.time;
			stageClearCount = instance.stageClearCount;
			Scene activeScene = SceneManager.GetActiveScene();
			sceneName = ((Scene)(ref activeScene)).name;
			nextSceneName = instance.nextStageScene.cachedName;
			shopPortalCount = instance.shopPortalCount;
			itemMask = new ItemMaskData(instance.availableItems);
			equipmentMask = new EquipmentMaskData(instance.availableEquipment);
			runRng = Saving.PreStageRng;
			eventFlags = instance.eventFlags.ToArray();
			trialArtifact = Object.FindObjectOfType<ArtifactTrialMissionController>()?.currentArtifactIndex ?? (-1);
			ruleBook = new RuleBookData(instance.ruleBook);
			if (instance is InfiniteTowerRun)
			{
				typedRunData = new InfiniteTowerTypedRunData();
				typeRunDataType = typeof(InfiniteTowerTypedRunData).AssemblyQualifiedName;
			}
		}

		internal void LoadData()
		{
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			ModSupport.ShareSuiteMapTransition();
			if (trialArtifact != -1)
			{
				ArtifactTrialMissionController.trialArtifact = ArtifactCatalog.GetArtifactDef((ArtifactIndex)trialArtifact);
			}
			Run instance = Run.instance;
			if (ruleBook.ruleValues.Length != RuleCatalog.ruleCount)
			{
				ProperSavePlugin.InstanceLogger.LogError((object)"RuleCatalog mismatch with saved ruleBook data, fallback to starting Run ruleBook");
			}
			else
			{
				instance.SetRuleBook(ruleBook.Load());
			}
			instance.OnRuleBookUpdated(instance.networkRuleBookComponent);
			instance.seed = seed;
			instance.selectedDifficulty = (DifficultyIndex)difficulty;
			instance.shopPortalCount = shopPortalCount;
			runRng.LoadData(instance);
			instance.GenerateStageRNG();
			typedRunData?.Load();
			instance.allowNewParticipants = true;
			Object.DontDestroyOnLoad((Object)(object)((Component)instance).gameObject);
			ReadOnlyCollection<NetworkUser> readOnlyInstancesList = NetworkUser.readOnlyInstancesList;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				instance.OnUserAdded(readOnlyInstancesList[i]);
			}
			instance.allowNewParticipants = false;
			instance.stageClearCount = stageClearCount;
			instance.RecalculateDifficultyCoefficent();
			instance.nextStageScene = SceneCatalog.GetSceneDefFromSceneName(nextSceneName);
			NetworkManager.singleton.ServerChangeScene(sceneName);
			itemMask.LoadDataOut(out instance.availableItems);
			equipmentMask.LoadDataOut(out instance.availableEquipment);
			instance.BuildUnlockAvailability();
			instance.BuildDropTable();
			string[] array = eventFlags;
			foreach (string eventFlag in array)
			{
				instance.SetEventFlag(eventFlag);
			}
			instance.isRunning = true;
			if (onRunStartGlobalDelegate.GetValue(null) is MulticastDelegate multicastDelegate && (object)multicastDelegate != null)
			{
				Delegate[] invocationList = multicastDelegate.GetInvocationList();
				foreach (Delegate @delegate in invocationList)
				{
					@delegate.Method.Invoke(@delegate.Target, new object[1] { instance });
				}
			}
			instance.fixedTime = fixedTime;
			instance.time = time;
			instance.runStopwatch = new RunStopwatch
			{
				offsetFromFixedTime = offsetFromFixedTime,
				isPaused = isPaused
			};
		}
	}
	public class RunRngData
	{
		[DataMember(Name = "rr")]
		public RngData runRng;

		[DataMember(Name = "nsr")]
		public RngData nextStageRng;

		[DataMember(Name = "srg")]
		public RngData stageRngGenerator;

		internal RunRngData(Run run)
		{
			runRng = new RngData(run.runRNG);
			nextStageRng = new RngData(run.nextStageRng);
			stageRngGenerator = new RngData(run.stageRngGenerator);
		}

		internal void LoadData(Run run)
		{
			runRng.LoadDataOut(out run.runRNG);
			nextStageRng.LoadDataOut(out run.nextStageRng);
			stageRngGenerator.LoadDataOut(out run.stageRngGenerator);
		}
	}
	public class TeamData
	{
		[DataMember(Name = "e")]
		public long expirience;

		internal TeamData()
		{
			expirience = (long)TeamManager.instance.GetTeamExperience((TeamIndex)1);
		}

		internal void LoadData()
		{
			TeamManager.instance.GiveTeamExperience((TeamIndex)1, (ulong)expirience);
		}
	}
}
namespace ProperSave.SaveData.Runs
{
	public class InfiniteTowerTypedRunData : ITypedRunData
	{
		[DataMember(Name = "wi")]
		public int waveIndex;

		[DataMember(Name = "wr")]
		public RngData waveRng;

		[DataMember(Name = "eir")]
		public RngData enemyItemRng;

		[DataMember(Name = "swr")]
		public RngData safeWardRng;

		[DataMember(Name = "eipi")]
		public int enemyItemPatternIndex;

		[DataMember(Name = "ei")]
		public InventoryData enemyInventory;

		internal InfiniteTowerTypedRunData()
		{
			Run instance = Run.instance;
			InfiniteTowerRun val = (InfiniteTowerRun)(object)((instance is InfiniteTowerRun) ? instance : null);
			waveIndex = val.waveIndex;
			waveRng = new RngData(val.waveRng);
			enemyItemRng = new RngData(val.enemyItemRng);
			safeWardRng = Saving.PreStageInfiniteTowerSafeWardRng;
			enemyItemPatternIndex = val.enemyItemPatternIndex;
			enemyInventory = new InventoryData(val.enemyInventory);
		}

		void ITypedRunData.Load()
		{
			Run instance = Run.instance;
			InfiniteTowerRun val = (InfiniteTowerRun)(object)((instance is InfiniteTowerRun) ? instance : null);
			val._waveIndex = waveIndex;
			waveRng.LoadDataRef(ref val.waveRng);
			enemyItemRng.LoadDataRef(ref val.enemyItemRng);
			safeWardRng.LoadDataRef(ref val.safeWardRng);
			val.enemyItemPatternIndex = enemyItemPatternIndex;
			enemyInventory.LoadInventory(val.enemyInventory);
		}
	}
	public interface ITypedRunData
	{
		void Load();
	}
}
namespace ProperSave.SaveData.Artifacts
{
	public class EnigmaData
	{
		[DataMember(Name = "sier")]
		public RngData serverInitialEquipmentRng;

		[DataMember(Name = "saer")]
		public RngData serverActivationEquipmentRng;

		internal EnigmaData()
		{
			serverInitialEquipmentRng = new RngData(EnigmaArtifactManager.serverInitialEquipmentRng);
			serverActivationEquipmentRng = new RngData(EnigmaArtifactManager.serverActivationEquipmentRng);
		}

		internal void LoadData()
		{
			serverInitialEquipmentRng.LoadDataRef(ref EnigmaArtifactManager.serverInitialEquipmentRng);
			serverActivationEquipmentRng.LoadDataRef(ref EnigmaArtifactManager.serverActivationEquipmentRng);
		}
	}
}
namespace ProperSave.TinyJson
{
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	internal sealed class DiscoverObjectTypeAttribute : Attribute
	{
		private string MemberName { get; }

		public DiscoverObjectTypeAttribute(string memberName)
		{
			MemberName = memberName;
		}

		public Type GetObjectType(object instance)
		{
			if (MemberName == null)
			{
				return null;
			}
			MemberInfo memberInfo = instance?.GetType()?.GetMember(MemberName)?.FirstOrDefault();
			string typeName;
			if (!(memberInfo is FieldInfo fieldInfo))
			{
				if (!(memberInfo is PropertyInfo propertyInfo))
				{
					throw new NotSupportedException();
				}
				typeName = propertyInfo.GetValue(instance) as string;
			}
			else
			{
				typeName = fieldInfo.GetValue(instance) as string;
			}
			return Type.GetType(typeName, throwOnError: false);
		}
	}
}
namespace ProperSave.Data
{
	public class CharacterMasterData
	{
		[DataMember(Name = "bn")]
		public string bodyName;

		[DataMember(Name = "m")]
		public uint money;

		[DataMember(Name = "i")]
		public InventoryData inventory;

		[DataMember(Name = "l")]
		public LoadoutData loadout;

		[DataMember(Name = "vc")]
		public uint voidCoins;

		[DataMember(Name = "cvrng")]
		public RngData cloverVoidRng;

		[DataMember(Name = "di")]
		public InventoryData devotionInventory;

		[DataMember(Name = "be")]
		public ulong beadExpirience;

		[DataMember(Name = "nobsg")]
		public int numberOfBeadStatsGained;

		[DataMember(Name = "obl")]
		public uint oldBeadLevel;

		[DataMember(Name = "nbl")]
		public uint newBeadLevel;

		[DataMember(Name = "bxpnfcl")]
		public ulong beadXPNeededForCurrentLevel;

		[DataMember(Name = "lssme")]
		public uint lssMoneyExp;

		[DataMember(Name = "ms")]
		public MinionData[] minions;

		internal CharacterMasterData(CharacterMaster master)
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			money = master.money;
			voidCoins = master.voidCoins;
			beadExpirience = master.beadExperience;
			numberOfBeadStatsGained = master.numberOfBeadStatsGained;
			oldBeadLevel = master.oldBeadLevel;
			newBeadLevel = master.newBeadLevel;
			beadXPNeededForCurrentLevel = master.beadXPNeededForCurrentLevel;
			lssMoneyExp = master.lssMoneyExp;
			inventory = new InventoryData(master.inventory);
			loadout = new LoadoutData(master.loadout);
			bodyName = ((Object)master.bodyPrefab).name;
			if (master.cloverVoidRng != null)
			{
				cloverVoidRng = new RngData(master.cloverVoidRng);
			}
			if (RunArtifactManager.instance.IsArtifactEnabled(Artifacts.Devotion))
			{
				DevotionInventoryController devotionInventoryController = GetDevotionInventoryController(master);
				if (Object.op_Implicit((Object)(object)devotionInventoryController))
				{
					devotionInventory = new InventoryData(devotionInventoryController._devotionMinionInventory);
				}
			}
			List<MinionData> list = new List<MinionData>();
			foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
			{
				CharacterMaster ownerMaster = readOnlyInstances.minionOwnership.ownerMaster;
				if ((Object)(object)ownerMaster != (Object)null && ((NetworkBehaviour)ownerMaster).netId == ((NetworkBehaviour)master).netId)
				{
					list.Add(new MinionData(readOnlyInstances));
				}
			}
			minions = new MinionData[list.Count];
			for (int i = 0; i < list.Count; i++)
			{
				minions[i] = list[i];
			}
		}

		internal void LoadMaster(CharacterMaster master, bool delayedInventory)
		{
			if (devotionInventory != null)
			{
				DevotionInventoryController val = CreateDevotionInventoryController(master);
				devotionInventory.LoadInventory(val._devotionMinionInventory);
			}
			MinionData[] array = minions;
			for (int i = 0; i < array.Length; i++)
			{
				array[i].LoadMinion(master);
			}
			GameObject val2 = BodyCatalog.FindBodyPrefab(bodyName);
			if (Object.op_Implicit((Object)(object)val2))
			{
				master.bodyPrefab = val2;
			}
			ModSupport.LoadShareSuiteMoney(money);
			master.money = money;
			master.voidCoins = voidCoins;
			master.beadExperience = beadExpirience;
			master.numberOfBeadStatsGained = numberOfBeadStatsGained;
			master.oldBeadLevel = oldBeadLevel;
			master.newBeadLevel = newBeadLevel;
			master.beadXPNeededForCurrentLevel = beadXPNeededForCurrentLevel;
			master.lssMoneyExp = lssMoneyExp;
			loadout.LoadData(master.loadout);
			cloverVoidRng?.LoadDataOut(out master.cloverVoidRng);
			if (delayedInventory)
			{
				((MonoBehaviour)master).StartCoroutine(LoadInventoryCoroutine(master, inventory));
			}
			else
			{
				inventory.LoadInventory(master.inventory);
			}
		}

		internal static DevotionInventoryController GetDevotionInventoryController(CharacterMaster master)
		{
			foreach (DevotionInventoryController instance in DevotionInventoryController.InstanceList)
			{
				if ((Object)(object)instance.SummonerMaster == (Object)(object)master)
				{
					return instance;
				}
			}
			return null;
		}

		private static DevotionInventoryController CreateDevotionInventoryController(CharacterMaster master)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(Addressables.LoadAssetAsync<GameObject>((object)"RoR2/CU8/LemurianEgg/DevotionMinionInventory.prefab").WaitForCompletion());
			DevotionInventoryController component = val.GetComponent<DevotionInventoryController>();
			((Component)component).GetComponent<TeamFilter>().teamIndex = (TeamIndex)1;
			component._summonerMaster = master;
			NetworkServer.Spawn(val);
			return component;
		}

		private static IEnumerator LoadInventoryCoroutine(CharacterMaster minionMaster, InventoryData inventory)
		{
			yield return (object)new WaitForEndOfFrame();
			yield return (object)new WaitForEndOfFrame();
			inventory.LoadInventory(minionMaster.inventory);
		}
	}
	public class DevotedLemurianData
	{
		[DataMember(Name = "ii")]
		public int itemIndex;

		[DataMember(Name = "dev")]
		public int devotedEvolutionLevel;

		public DevotedLemurianData(DevotedLemurianController controller)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			itemIndex = (int)controller.DevotionItem;
			devotedEvolutionLevel = controller.DevotedEvolutionLevel;
		}

		public void LoadData(DevotedLemurianController controller)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			controller._devotionItem = (ItemIndex)itemIndex;
			controller._devotedEvolutionLevel = devotedEvolutionLevel;
		}
	}
	public class EquipmentData
	{
		[DataMember(Name = "i")]
		public int index;

		[DataMember(Name = "c")]
		public byte charges;

		[DataMember(Name = "cft")]
		public float chargeFinishTime;

		public EquipmentData(EquipmentState state)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			index = (int)state.equipmentIndex;
			charges = state.charges;
			chargeFinishTime = state.chargeFinishTime.t;
		}

		public void LoadEquipment(Inventory inventory, byte equipmentSlot)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			FixedTimeStamp val = default(FixedTimeStamp);
			((FixedTimeStamp)(ref val))..ctor(chargeFinishTime);
			EquipmentState val2 = default(EquipmentState);
			((EquipmentState)(ref val2))..ctor((EquipmentIndex)index, val, charges, false);
			inventory.SetEquipment(val2, (uint)equipmentSlot);
		}
	}
	public class EquipmentMaskData
	{
		public bool[] array;

		public EquipmentMaskData(EquipmentMask mask)
		{
			array = mask.array.ToArray();
		}

		public void LoadDataOut(out EquipmentMask mask)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			mask = new EquipmentMask
			{
				array = array.ToArray()
			};
		}
	}
	public class InventoryData
	{
		[DataMember(Name = "ib")]
		public uint infusionBonus;

		[DataMember(Name = "ed")]
		public bool equipmentDisabled;

		[DataMember(Name = "bah")]
		public float beadAppliedHealth;

		[DataMember(Name = "bas")]
		public float beadAppliedShield;

		[DataMember(Name = "bar")]
		public float beadAppliedRegen;

		[DataMember(Name = "bad")]
		public float beadAppliedDamage;

		[DataMember(Name = "i")]
		public List<ItemData> items;

		[DataMember(Name = "e")]
		public EquipmentData[] equipments;

		[DataMember(Name = "aes")]
		public byte activeEquipmentSlot;

		public InventoryData(Inventory inventory)
		{
			//IL_0069: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected I4, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			infusionBonus = inventory.infusionBonus;
			equipmentDisabled = inventory.equipmentDisabled;
			beadAppliedDamage = inventory.beadAppliedDamage;
			beadAppliedHealth = inventory.beadAppliedHealth;
			beadAppliedRegen = inventory.beadAppliedRegen;
			beadAppliedShield = inventory.beadAppliedShield;
			items = new List<ItemData>();
			foreach (ItemIndex item in inventory.itemAcquisitionOrder)
			{
				items.Add(new ItemData
				{
					itemIndex = (int)item,
					count = inventory.GetItemCount(item)
				});
			}
			equipments = new EquipmentData[inventory.GetEquipmentSlotCount()];
			for (int i = 0; i < equipments.Length; i++)
			{
				equipments[i] = new EquipmentData(inventory.GetEquipment((uint)i));
			}
			activeEquipmentSlot = inventory.activeEquipmentSlot;
		}

		public void LoadInventory(Inventory inventory)
		{
			inventory.beadAppliedShield = beadAppliedShield;
			inventory.beadAppliedRegen = beadAppliedRegen;
			inventory.beadAppliedHealth = beadAppliedHealth;
			inventory.beadAppliedDamage = beadAppliedDamage;
			inventory.equipmentDisabled = equipmentDisabled;
			inventory.itemAcquisitionOrder.Clear();
			foreach (ItemData item in items)
			{
				inventory.itemStacks[item.itemIndex] = item.count;
				inventory.itemAcquisitionOrder.Add((ItemIndex)item.itemIndex);
			}
			inventory.HandleInventoryChanged();
			for (byte b = 0; b < equipments.Length; b++)
			{
				equipments[b].LoadEquipment(inventory, b);
			}
			inventory.SetActiveEquipmentSlot(activeEquipmentSlot);
			inventory.AddInfusionBonus(infusionBonus);
		}
	}
	public class ItemData
	{
		[DataMember(Name = "i")]
		public int itemIndex;

		[DataMember(Name = "c")]
		public int count;
	}
	public class ItemMaskData
	{
		public bool[] array;

		public ItemMaskData(ItemMask mask)
		{
			array = mask.array.ToArray();
		}

		public void LoadDataOut(out ItemMask mask)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			mask = new ItemMask
			{
				array = array.ToArray()
			};
		}
	}
	public class LoadoutData
	{
		public class LoadoutBodyData
		{
			[DataMember(Name = "bi")]
			public int bodyIndex;

			[DataMember(Name = "sp")]
			public uint skinPreference;

			[DataMember(Name = "sps")]
			public uint[] skillPreferences;

			public LoadoutBodyData(BodyLoadout bodyLoadout)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected I4, but got Unknown
				bodyIndex = (int)bodyLoadout.bodyIndex;
				skinPreference = bodyLoadout.skinPreference;
				skillPreferences = bodyLoadout.skillPreferences;
			}

			public BodyLoadout Load()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Expected O, but got Unknown
				return new BodyLoadout
				{
					bodyIndex = (BodyIndex)bodyIndex,
					skinPreference = skinPreference,
					skillPreferences = skillPreferences
				};
			}
		}

		[DataMember(Name = "ml")]
		public LoadoutBodyData[] modifiedLoadouts;

		public LoadoutData(Loadout loadout)
		{
			BodyLoadout[] modifiedBodyLoadouts = loadout.bodyLoadoutManager.modifiedBodyLoadouts;
			modifiedLoadouts = modifiedBodyLoadouts.Select((BodyLoadout el) => new LoadoutBodyData(el)).ToArray();
		}

		public void LoadData(Loadout loadout)
		{
			loadout.Clear();
			loadout.bodyLoadoutManager.modifiedBodyLoadouts = modifiedLoadouts.Select((LoadoutBodyData el) => el.Load()).ToArray();
		}
	}
	public class ModdedData
	{
		[DataMember(Name = "ot")]
		public string ObjectType { get; set; }

		[DataMember(Name = "v")]
		[DiscoverObjectType("ObjectType")]
		public object Value { get; set; }
	}
	public class RngData
	{
		[DataMember(Name = "s0")]
		public ulong state0;

		[DataMember(Name = "s1")]
		public ulong state1;

		public RngData(Xoroshiro128Plus rng)
		{
			state0 = rng.state0;
			state1 = rng.state1;
		}

		public void LoadDataOut(out Xoroshiro128Plus rng)
		{
			object uninitializedObject = FormatterServices.GetUninitializedObject(typeof(Xoroshiro128Plus));
			rng = (Xoroshiro128Plus)((uninitializedObject is Xoroshiro128Plus) ? uninitializedObject : null);
			LoadDataRef(ref rng);
		}

		public void LoadDataRef(ref Xoroshiro128Plus rng)
		{
			rng.state0 = state0;
			rng.state1 = state1;
		}
	}
	public class RuleBookData
	{
		[DataMember(Name = "rv")]
		public byte[] ruleValues;

		public RuleBookData(RuleBook ruleBook)
		{
			ruleValues = ruleBook.ruleValues.ToArray();
		}

		public RuleBook Load()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			return new RuleBook
			{
				ruleValues = ruleValues.ToArray()
			};
		}
	}
	public class UserIDData
	{
		[DataMember(Name = "s")]
		public ulong steam;

		[DataMember(Name = "e")]
		public string egs;

		[DataMember(Name = "si")]
		public byte subId;

		public UserIDData(NetworkUserId userID)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			egs = userID.strValue;
			steam = userID.value;
			subId = userID.subId;
		}

		public NetworkUserId Load()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (steam != 0L)
			{
				return new NetworkUserId(steam, subId);
			}
			if (!string.IsNullOrWhiteSpace(egs))
			{
				return new NetworkUserId(egs, subId);
			}
			return default(NetworkUserId);
		}
	}
}
namespace ProperSave.Components
{
	public class GamepadTooltipProvider : TooltipProvider
	{
		public HoldGamepadInputEvent inputEvent;

		private RectTransform rectTransform;

		private InputBindingDisplayController inputBindingDisplayController;

		public void Awake()
		{
			rectTransform = ((Component)this).GetComponent<RectTransform>();
			inputBindingDisplayController = ((Component)this).GetComponent<InputBindingDisplayController>();
		}

		public void Start()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			inputBindingDisplayController.useExplicitInputSource = false;
			inputEvent.holdStartEvent.AddListener(new UnityAction(HoldStart));