Decompiled source of ProperSave v3.0.3

plugins/ProperSave/ProperSave.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BiggerBazaar;
using HG;
using HG.Reflection;
using IL.RoR2;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour.HookGen;
using On.RoR2;
using On.RoR2.UI;
using PSTinyJson;
using ProperSave.Components;
using ProperSave.Data;
using ProperSave.Old;
using ProperSave.Old.Data;
using ProperSave.Old.SaveData;
using ProperSave.Old.SaveData.Artifacts;
using ProperSave.Old.SaveData.Runs;
using ProperSave.SaveData;
using ProperSave.SaveData.Artifacts;
using ProperSave.SaveData.Runs;
using ProperSave.TinyJson;
using ProperSave.Utils;
using R2API;
using RoR2;
using RoR2.Artifacts;
using RoR2.CharacterAI;
using RoR2.ContentManagement;
using RoR2.ExpansionManagement;
using RoR2.Networking;
using RoR2.Skills;
using RoR2.Stats;
using RoR2.UI;
using ShareSuite;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zio;
using Zio.FileSystems;

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

		[ThreadStatic]
		private static StringBuilder stringBuilder;

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

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

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

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

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

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

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

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

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

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

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

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

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

		public static readonly string PROPER_SAVE_TITLE_CONTINUE = "PROPER_SAVE_TITLE_CONTINUE";

		public static readonly string PROPER_SAVE_TITLE_LOAD = "PROPER_SAVE_TITLE_LOAD";

		public static readonly string PROPER_SAVE_CHAT_SAVE = "PROPER_SAVE_CHAT_SAVE";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_SAVED = "PROPER_SAVE_QUIT_DIALOG_SAVED";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE = "PROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE";

		public static readonly string PROPER_SAVE_QUIT_DIALOG_NOT_SAVED = "PROPER_SAVE_QUIT_DIALOG_NOT_SAVED";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_TITLE = "PROPER_SAVE_TOOLTIP_LOAD_TITLE";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_BODY = "PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_BODY";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_CHARACTER = "PROPER_SAVE_TOOLTIP_LOAD_DESCRIPTION_CHARACTER";

		public static readonly string PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH = "PROPER_SAVE_TOOLTIP_LOAD_CONTENT_MISMATCH";

		public static readonly string PROPER_SAVE_CHAT_SAVE_FAILED = "PROPER_SAVE_CHAT_SAVE_FAILED";
	}
	public static class Loading
	{
		[CompilerGenerated]
		private sealed class <LoadForceCoroutine>d__22 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadForceCoroutine>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Console.instance.SubmitCmd((NetworkUser)null, "host 0", false);
					<>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)PreGameController.instance != (Object)null));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					PreGameController.instance.StartRun();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadLobby>d__20 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadLobby>d__20(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				if ((Object)(object)PreGameController.instance == (Object)null)
				{
					ProperSavePlugin.InstanceLogger.LogInfo((object)"PreGameController instance not found");
					return false;
				}
				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");
					return false;
				}
				SaveFileMetadata currentLobbySaveMetadata = SaveFileMetadata.GetCurrentLobbySaveMetadata();
				if (currentLobbySaveMetadata == null)
				{
					ProperSavePlugin.InstanceLogger.LogInfo((object)"Save file for current users is not found");
					return false;
				}
				UPath? filePath = currentLobbySaveMetadata.FilePath;
				if (!filePath.HasValue)
				{
					ProperSavePlugin.InstanceLogger.LogInfo((object)"Metadata doesn't contain file name for the save file");
					return false;
				}
				if (!ProperSavePlugin.SavesFileSystem.FileExists(filePath.Value))
				{
					ProperSavePlugin.InstanceLogger.LogInfo((object)$"File \"{filePath}\" is not found");
					return false;
				}
				currentLobbySaveMetadata.ReadBody();
				ProperSavePlugin.CurrentSave = currentLobbySaveMetadata;
				IsLoading = true;
				if (currentLobbySaveMetadata.Header.ContentHash != ProperSavePlugin.ContentHash)
				{
					ProperSavePlugin.InstanceLogger.LogWarning((object)"Loading run but content mismatch detected which may result in errors");
				}
				PreGameController.instance.StartRun();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static bool isLoading;

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

		public static bool FirstRunStage { get; internal set; }

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

		public static event Action<SaveFile> OnLoadingStarted;

		public static event Action<SaveFile> OnLoadingEnded;

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

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

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

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

		[IteratorStateMachine(typeof(<LoadLobby>d__20))]
		internal static IEnumerator LoadLobby()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadLobby>d__20(0);
		}

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

		[IteratorStateMachine(typeof(<LoadForceCoroutine>d__22))]
		private static IEnumerator LoadForceCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadForceCoroutine>d__22(0);
		}
	}
	internal static class LobbyUI
	{
		private static GameObject lobbyButton;

		private static GameObject lobbySubmenuLegend;

		private static GameObject lobbyGlyphAndDescription;

		private static TooltipProvider tooltipProvider;

		private static GamepadTooltipProvider gamepadTooltipProvider;

		private static SaveFileMetadata lastFileMetadata;

		private static TooltipContent lastTooltipContent;

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

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

		private CharacterMaster master;

		public uint lunarCoins;

		public NetworkUserId userID;

		public BodyIndex bodyIndexPreference;

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

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

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

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

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

		private static void OnNetworkUserLost(NetworkUser networkUser)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)networkUser.master))
			{
				LostNetworkUser lostNetworkUser = ((Component)networkUser.master).gameObject.AddComponent<LostNetworkUser>();
				lostNetworkUser.lunarCoins = networkUser.lunarCoins;
				lostNetworkUser.userID = networkUser.id;
				lostNetworkUser.bodyIndexPreference = networkUser.bodyIndexPreference;
			}
		}
	}
	internal static class ModCompat
	{
		[CompilerGenerated]
		private sealed class <LoadShareSuiteMoneyInternal>d__23 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public uint money;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadShareSuiteMoneyInternal>d__23(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitUntil((Func<bool>)(() => !MoneySharingHooks.MapTransitionActive));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					MoneySharingHooks.SharedMoneyValue = (int)money;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string BiggerBazaarGUID = "com.MagnusMagnuson.BiggerBazaar";

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

		public static bool IsBBLoaded { get; private set; }

		public static bool IsSSLoaded { get; private set; }

		public static bool IsR2APIDifficultyLoaded { get; private set; }

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


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

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

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

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

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

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

		[MethodImpl(MethodImplOptions.NoInlining)]
		[IteratorStateMachine(typeof(<LoadShareSuiteMoneyInternal>d__23))]
		private static IEnumerator LoadShareSuiteMoneyInternal(uint money)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadShareSuiteMoneyInternal>d__23(0)
			{
				money = money
			};
		}

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

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

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static DifficultyIndex FindR2APIDifficultyIndex(string nameToken)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			foreach (var (result, val3) in DifficultyAPI.difficultyDefinitions)
			{
				if (val3.nameToken == nameToken)
				{
					return result;
				}
			}
			return (DifficultyIndex)(-1);
		}
	}
	[BepInPlugin("com.KingEnderBrine.ProperSave", "Proper Save", "3.0.3")]
	public class ProperSavePlugin : BaseUnityPlugin
	{
		public const string GUID = "com.KingEnderBrine.ProperSave";

		public const string Name = "Proper Save";

		public const string Version = "3.0.3";

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

		internal static ProperSavePlugin Instance { get; private set; }

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

		internal static FileSystem SavesFileSystem { get; private set; }

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


		private static string SavesDirectory { get; set; }

		internal static SaveFileMetadata CurrentSave { get; set; }

		internal static string ContentHash { get; private set; }

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

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

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

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

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

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

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

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

		private void ContentManagerOnContentPacksAssigned(ReadOnlyArray<ReadOnlyContentPack> contentPacks)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			MD5 mD = MD5.Create();
			StringWriter writer = new StringWriter();
			try
			{
				Enumerator<ReadOnlyContentPack> enumerator = contentPacks.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ReadOnlyContentPack current = enumerator.Current;
						writer.Write(((ReadOnlyContentPack)(ref current)).identifier);
						writer.Write(';');
						WriteCollection<ArtifactDef>(((ReadOnlyContentPack)(ref current)).artifactDefs, "artifactDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).bodyPrefabs, "bodyPrefabs");
						WriteCollection<EquipmentDef>(((ReadOnlyContentPack)(ref current)).equipmentDefs, "equipmentDefs");
						WriteCollection<DroneDef>(((ReadOnlyContentPack)(ref current)).droneDefs, "droneDefs");
						WriteCollection<ExpansionDef>(((ReadOnlyContentPack)(ref current)).expansionDefs, "expansionDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).gameModePrefabs, "gameModePrefabs");
						WriteCollection<ItemDef>(((ReadOnlyContentPack)(ref current)).itemDefs, "itemDefs");
						WriteCollection<ItemTierDef>(((ReadOnlyContentPack)(ref current)).itemTierDefs, "itemTierDefs");
						WriteCollection<GameObject>(((ReadOnlyContentPack)(ref current)).masterPrefabs, "masterPrefabs");
						WriteCollection<SceneDef>(((ReadOnlyContentPack)(ref current)).sceneDefs, "sceneDefs");
						WriteCollection<SkillDef>(((ReadOnlyContentPack)(ref current)).skillDefs, "skillDefs");
						WriteCollection<SkillFamily>(((ReadOnlyContentPack)(ref current)).skillFamilies, "skillFamilies");
						WriteCollection<SurvivorDef>(((ReadOnlyContentPack)(ref current)).survivorDefs, "survivorDefs");
						WriteCollection<UnlockableDef>(((ReadOnlyContentPack)(ref current)).unlockableDefs, "unlockableDefs");
					}
				}
				finally
				{
					((IDisposable)enumerator).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
	{
		internal static readonly int currentVersion = 1;

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

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

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

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

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


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


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

		internal SaveFile()
		{
		}

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

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

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

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

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

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

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

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

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

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

		public DateTime SaveDate { get; internal set; }

		public string UserProfileId { get; internal set; }

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

		public GameModeIndex GameMode { get; internal set; }

		public string SceneName { get; internal set; }

		public DifficultyIndex Difficulty { get; internal set; }

		public int Time { get; internal set; }

		public int StageClearCount { get; internal set; }

		public string ContentHash { get; internal set; }

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

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

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

			public List<NetworkUserId> users;

			internal bool <GetCurrentLobbySaveMetadata>b__1(SaveFileMetadata el)
			{
				//IL_0020: 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)
				if (el.Header.Users.Length != users.Count || el.Header.GameMode != gameMode)
				{
					return false;
				}
				return users.DifferenceCount(el.Header.Users.Select((HeaderUserData e) => (e?.UserId?.Load()).GetValueOrDefault())) == 0;
			}
		}

		public string FileName { get; internal set; }

		public bool ForceLoad { get; internal set; }

		public SaveFileHeader Header { get; internal set; }

		public long BodyOffset { get; internal set; }

		public SaveFile Body { get; internal set; }

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

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


		internal void FillMetadataForCurrentLobby()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			ForceLoad = false;
			Header = new SaveFileHeader();
			Body = new SaveFile();
			BodyOffset = 0L;
			Header.FillFromCurrentRun();
			Body.FillFromCurrentRun();
			if (FileName == null)
			{
				do
				{
					FileName = Guid.NewGuid().ToString();
				}
				while (ProperSavePlugin.SavesFileSystem.FileExists(FilePath.Value));
			}
		}

		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__DisplayClass26_0 CS$<>8__locals0 = new <>c__DisplayClass26_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__DisplayClass26_0)num).gameMode = (GameModeIndex)obj;
				if ((int)CS$<>8__locals0.gameMode == -1)
				{
					return null;
				}
				if (CS$<>8__locals0.users.Count == 1)
				{
					<>c__DisplayClass26_0 <>c__DisplayClass26_ = CS$<>8__locals0;
					string profile = Path.GetFileNameWithoutExtension(LocalUserManager.readOnlyLocalUsersList[0].userProfile.fileName);
					return SavesMetadata.FirstOrDefault((SaveFileMetadata el) => el.Header.UserProfileId == profile && el.Header.Users.Length == 1 && el.Header.GameMode == <>c__DisplayClass26_.gameMode);
				}
				return SavesMetadata.FirstOrDefault((SaveFileMetadata el) => el.Header.Users.Length == CS$<>8__locals0.users.Count && el.Header.GameMode == CS$<>8__locals0.gameMode && CS$<>8__locals0.users.DifferenceCount(el.Header.Users.Select((HeaderUserData e) => (e?.UserId?.Load()).GetValueOrDefault())) == 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (!ProperSavePlugin.SavesFileSystem.DirectoryExists(ProperSavePlugin.SavesPath))
			{
				ProperSavePlugin.SavesFileSystem.CreateDirectory(ProperSavePlugin.SavesPath);
				return;
			}
			SavesMetadata.Clear();
			List<SaveFileMetadata> list = new List<SaveFileMetadata>();
			foreach (UPath item in FileSystemExtensions.EnumerateFiles((IFileSystem)(object)ProperSavePlugin.SavesFileSystem, ProperSavePlugin.SavesPath, "*.bin"))
			{
				try
				{
					SaveFileMetadata saveFileMetadata = new SaveFileMetadata();
					saveFileMetadata.FileName = UPathExtensions.GetNameWithoutExtension(item);
					saveFileMetadata.ReadHeader();
					list.Add(saveFileMetadata);
				}
				catch (Exception ex)
				{
					ProperSavePlugin.InstanceLogger.LogWarning((object)("Failed to load save file \"" + UPathExtensions.GetName(item) + "\""));
					ProperSavePlugin.InstanceLogger.LogError((object)ex);
				}
			}
			SavesMetadata.AddRange(from el in list
				orderby el.Header.ContentHash == ProperSavePlugin.ContentHash descending, el.Header.SaveDate descending
				select el);
		}

		internal static void Replace(SaveFileMetadata metadata, SaveFileMetadata oldMetadata)
		{
			if (oldMetadata != null)
			{
				SavesMetadata.Remove(oldMetadata);
			}
			SavesMetadata.Insert(0, metadata);
		}

		internal void Write(bool resilient)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter writer = new BinaryWriter(memoryStream);
			Header.Write(writer, resilient);
			Body.Write(writer, resilient);
			using Stream destination = ProperSavePlugin.SavesFileSystem.OpenFile(FilePath.Value, FileMode.Create, FileAccess.Write, FileShare.None);
			memoryStream.Seek(0L, SeekOrigin.Begin);
			memoryStream.CopyTo(destination);
		}

		internal void ReadBody()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Body != null)
			{
				return;
			}
			using Stream stream = ProperSavePlugin.SavesFileSystem.OpenFile(FilePath.Value, FileMode.Open, FileAccess.Read, FileShare.None);
			stream.Seek(BodyOffset, SeekOrigin.Begin);
			using BinaryReader reader = new BinaryReader(stream);
			Body = SaveFile.Read(reader);
		}

		internal void ReadHeader()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Header != null)
			{
				return;
			}
			using Stream stream = ProperSavePlugin.SavesFileSystem.OpenFile(FilePath.Value, FileMode.Open, FileAccess.Read, FileShare.None);
			using BinaryReader reader = new BinaryReader(stream);
			Header = SaveFileHeader.Read(reader);
			BodyOffset = stream.Position;
			ForceLoad = false;
		}

		internal void ReadForce(string path)
		{
			using FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
			using BinaryReader reader = new BinaryReader(fileStream);
			Header = SaveFileHeader.Read(reader);
			BodyOffset = fileStream.Position;
			Body = SaveFile.Read(reader);
			ForceLoad = true;
		}
	}
	internal static class Saving
	{
		internal static ProperSave.SaveData.RunRngData PreStageRng { get; private set; }

		internal static ProperSave.Data.RngData PreStageInfiniteTowerSafeWardRng { get; private set; }

		internal static string PreStageSceneName { 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.AdvanceStage += new hook_AdvanceStage(RunAdvanceStage);
			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.AdvanceStage -= new hook_AdvanceStage(RunAdvanceStage);
			QuitConfirmationHelper.IssueQuitCommand_Action -= new Manipulator(IssueQuitCommandIL);
		}

		private static void RunAdvanceStage(orig_AdvanceStage orig, Run self, SceneDef sceneDef)
		{
			PreStageSceneName = SceneCatalog.GetSceneDefForCurrentScene().cachedName;
			PreStageRng = ProperSave.SaveData.RunRngData.Create(Run.instance);
			InfiniteTowerRun val = (InfiniteTowerRun)(object)((self is InfiniteTowerRun) ? self : null);
			if (val != null)
			{
				PreStageInfiniteTowerSafeWardRng = ProperSave.Data.RngData.Create(val.safeWardRng);
			}
			orig.Invoke(self, sceneDef);
		}

		private static void RunOnServerGameOver(Run run, GameEndingDef ending)
		{
			//IL_0027: 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)
			try
			{
				SaveFileMetadata currentSave = ProperSavePlugin.CurrentSave;
				if (currentSave != null && currentSave.FilePath.HasValue)
				{
					if (ProperSavePlugin.SavesFileSystem.FileExists(currentSave.FilePath.Value))
					{
						ProperSavePlugin.SavesFileSystem.DeleteFile(currentSave.FilePath.Value);
					}
					ProperSavePlugin.CurrentSave = null;
					SaveFileMetadata.SavesMetadata.Remove(currentSave);
				}
			}
			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)
				{
					SaveFileMetadata currentSave = ProperSavePlugin.CurrentSave;
					if (currentSave == null || !currentSave.ForceLoad)
					{
						SaveGame();
					}
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
			finally
			{
				orig.Invoke(self);
			}
		}

		private static void SaveGame()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			SaveFileMetadata currentLobbySaveMetadata = SaveFileMetadata.GetCurrentLobbySaveMetadata();
			SaveFileMetadata saveFileMetadata = new SaveFileMetadata
			{
				FileName = currentLobbySaveMetadata?.FileName
			};
			saveFileMetadata.FillMetadataForCurrentLobby();
			try
			{
				saveFileMetadata.Write(ProperSavePlugin.Resilient.Value);
				ProperSavePlugin.CurrentSave = saveFileMetadata;
				SaveFileMetadata.Replace(saveFileMetadata, currentLobbySaveMetadata);
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = string.Format(Language.GetString(LanguageConsts.PROPER_SAVE_CHAT_SAVE), Language.GetString(SceneCatalog.currentSceneDef.nameToken))
				});
			}
			catch (Exception ex)
			{
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = string.Format(Language.GetString(LanguageConsts.PROPER_SAVE_CHAT_SAVE_FAILED), Language.GetString(SceneCatalog.currentSceneDef.nameToken))
				});
				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.Header.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.Header.StageClearCount).ToString() };
				((TMP_Text)descriptionLabel3).text = text + Language.GetStringFormatted(pROPER_SAVE_QUIT_DIALOG_SAVED_BEFORE, array);
			}
		}
	}
}
namespace ProperSave.Utils
{
	public static class CatalogHelpers
	{
		private static Dictionary<string, DroneIndex> DroneNameToIndex { get; set; }

		public static DifficultyIndex FindDifficultyIndex(string nameToken)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (ModCompat.IsR2APIDifficultyLoaded)
				{
					return ModCompat.FindR2APIDifficultyIndex(nameToken);
				}
			}
			catch (Exception ex)
			{
				ProperSavePlugin.InstanceLogger.LogError((object)ex);
			}
			for (int i = 0; i < DifficultyCatalog.difficultyDefs.Length; i++)
			{
				if (DifficultyCatalog.difficultyDefs[i].nameToken == nameToken)
				{
					return (DifficultyIndex)i;
				}
			}
			return (DifficultyIndex)(-1);
		}

		public static DroneIndex FindDroneIndex(string name)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (DroneNameToIndex == null)
			{
				DroneNameToIndex = DroneCatalog.droneDefs.ToDictionary((DroneDef d) => ((Object)d).name, (DroneDef d) => d.droneIndex);
			}
			if (DroneNameToIndex.TryGetValue(name, out var value))
			{
				return value;
			}
			return (DroneIndex)(-1);
		}
	}
	public class ReaderContext
	{
		public BinaryReader Reader { get; set; }

		public string[] SharedStrings { get; set; }

		public bool Resilient { get; set; }

		public int Version { get; set; }
	}
	public static class SharedIndexHelpers
	{
		public static int FromDifficulty(DifficultyIndex difficultyIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)difficultyIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)difficultyIndex;
			}
			DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(difficultyIndex);
			return context.SharedStrings.AddOrIndexOf(difficultyDef.nameToken);
		}

		public static DifficultyIndex ResolveDifficulty(int sharedIndex, ReaderContext context)
		{
			//IL_001a: 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)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (DifficultyIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (DifficultyIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			DifficultyIndex val = CatalogHelpers.FindDifficultyIndex(text);
			if ((int)val == -1)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find difficulty \"" + text + "\" in DifficultyCatalog"));
				return (DifficultyIndex)(-1);
			}
			return val;
		}

		public static int FromRule(int ruleIndex, WriterContext context)
		{
			if (!context.Resilient || ruleIndex == -1)
			{
				return ruleIndex;
			}
			RuleDef ruleDef = RuleCatalog.GetRuleDef(ruleIndex);
			return context.SharedStrings.AddOrIndexOf(ruleDef.globalName);
		}

		public static int ResolveRule(int sharedIndex, ReaderContext context)
		{
			if (sharedIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			RuleDef val = RuleCatalog.FindRuleDef(text);
			if (val == null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find rule \"" + text + "\" in RuleCatalog"));
				return -1;
			}
			return val.globalIndex;
		}

		public static int FromArtifact(ArtifactIndex artifactIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)artifactIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)artifactIndex;
			}
			ArtifactDef artifactDef = ArtifactCatalog.GetArtifactDef(artifactIndex);
			return context.SharedStrings.AddOrIndexOf(artifactDef.cachedName);
		}

		public static ArtifactIndex ResolveArtifact(int sharedIndex, ReaderContext context)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (ArtifactIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (ArtifactIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			ArtifactDef val = ArtifactCatalog.FindArtifactDef(text);
			if ((Object)(object)val == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find artifact \"" + text + "\" in ArtifactCatalog"));
				return (ArtifactIndex)(-1);
			}
			return val.artifactIndex;
		}

		public static int FromBody(BodyIndex bodyIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)bodyIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)bodyIndex;
			}
			string bodyName = BodyCatalog.GetBodyName(bodyIndex);
			return context.SharedStrings.AddOrIndexOf(bodyName);
		}

		public static BodyIndex ResolveBody(int sharedIndex, ReaderContext context)
		{
			//IL_001a: 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)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (BodyIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (BodyIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			BodyIndex val = BodyCatalog.FindBodyIndex(text);
			if ((int)val == -1)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find body \"" + text + "\" in BodyCatalog"));
				return (BodyIndex)(-1);
			}
			return val;
		}

		public static int FromStatField(int statIndex, WriterContext context)
		{
			if (!context.Resilient || statIndex == -1)
			{
				return statIndex;
			}
			StatDef val = StatDef.allStatDefs[statIndex];
			return context.SharedStrings.AddOrIndexOf(val.name);
		}

		public static int ResolveStatField(int sharedIndex, ReaderContext context)
		{
			if (sharedIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			StatDef val = StatDef.Find(text);
			if (val == null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find stat \"" + text + "\" in StatDef"));
				return -1;
			}
			return val.index;
		}

		public static int FromUnlockable(UnlockableIndex unlockableIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)unlockableIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)unlockableIndex;
			}
			UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(unlockableIndex);
			return context.SharedStrings.AddOrIndexOf(unlockableDef.cachedName);
		}

		public static UnlockableIndex ResolveUnlockable(int sharedIndex, ReaderContext context)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (UnlockableIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (UnlockableIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(text);
			if ((Object)(object)unlockableDef == (Object)null)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find unlockable \"" + text + "\" in UnlockableCatalog"));
				return (UnlockableIndex)(-1);
			}
			return unlockableDef.index;
		}

		public static int FromMaster(MasterIndex masterIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (masterIndex == MasterIndex.none)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return masterIndex.i;
			}
			string masterName = MasterCatalog.GetMasterName(masterIndex);
			return context.SharedStrings.AddOrIndexOf(masterName);
		}

		public static MasterIndex ResolveMaster(int sharedIndex, ReaderContext context)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return MasterIndex.none;
			}
			if (!context.Resilient)
			{
				return new MasterIndex(sharedIndex);
			}
			string text = context.SharedStrings[sharedIndex];
			MasterIndex val = MasterCatalog.FindMasterIndex(text);
			if (val == MasterIndex.none)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find master \"" + text + "\" in MasterCatalog"));
				return MasterIndex.none;
			}
			return val;
		}

		public static int FromItem(ItemIndex itemIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)itemIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)itemIndex;
			}
			ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
			return context.SharedStrings.AddOrIndexOf(((Object)itemDef).name);
		}

		public static ItemIndex ResolveItem(int sharedIndex, ReaderContext context)
		{
			//IL_001a: 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)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (ItemIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (ItemIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			ItemIndex val = ItemCatalog.FindItemIndex(text);
			if ((int)val == -1)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find item \"" + text + "\" in ItemCatalog"));
				return (ItemIndex)(-1);
			}
			return val;
		}

		public static int FromEquipment(EquipmentIndex equipmentIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int)equipmentIndex == -1)
			{
				return -1;
			}
			if (!context.Resilient)
			{
				return (int)equipmentIndex;
			}
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex);
			return context.SharedStrings.AddOrIndexOf(((Object)equipmentDef).name);
		}

		public static EquipmentIndex ResolveEquipment(int sharedIndex, ReaderContext context)
		{
			//IL_001a: 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)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (sharedIndex == -1)
			{
				return (EquipmentIndex)(-1);
			}
			if (!context.Resilient)
			{
				return (EquipmentIndex)sharedIndex;
			}
			string text = context.SharedStrings[sharedIndex];
			EquipmentIndex val = EquipmentCatalog.FindEquipmentIndex(text);
			if ((int)val == -1)
			{
				ProperSavePlugin.InstanceLogger.LogWarning((object)("Couldn't find equipment \"" + text + "\" in EquipmentCatalog"));
				return (EquipmentIndex)(-1);
			}
			return val;
		}

		public static int FromDrone(DroneIndex droneIndex, WriterContext context)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected I4, but got Unknown
			if ((int