Decompiled source of AutoSaver v1.2.0

plugins/Marioalexsan.AutoSaver.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Marioalexsan.AutoSaver.HarmonyReversePatches;
using Marioalexsan.AutoSaver.SoftDependencies;
using Microsoft.CodeAnalysis;
using Nessie.ATLYSS.EasySettings;
using Nessie.ATLYSS.EasySettings.UIElements;
using UnityEngine;
using UnityEngine.Events;

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

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Marioalexsan.AutoSaver
{
	[BepInPlugin("Marioalexsan.AutoSaver", "AutoSaver", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class AutoSaver : BaseUnityPlugin
	{
		public const string MoreBankTabsIndentifier = "com.16mb.morebanktabs";

		private static AutoSaver? _plugin;

		private readonly Harmony _harmony;

		private TimeSpan _elapsedAutosaveTime;

		private readonly char[] BannedChars;

		private readonly string ModDataFolderName;

		private bool _checkedForOldAutosaverBackups;

		public static AutoSaver Plugin => _plugin ?? throw new InvalidOperationException("AutoSaver hasn't been initialized yet. Either wait until initialization, or check via ChainLoader instead.");

		public ManualLogSource Logger { get; private set; }

		public ConfigEntry<bool> EnableAutosaving { get; private set; }

		public ConfigEntry<bool> SaveOnMapChange { get; private set; }

		public ConfigEntry<bool> EnableExperimentalFeatures { get; private set; }

		public ConfigEntry<bool> AppendSlotToSaveName { get; private set; }

		public ConfigEntry<KeyCode> SaveMultiplayerKeyCode { get; private set; }

		public ConfigEntry<int> BackupIntervalInMinutesConfig { get; private set; }

		public ConfigEntry<int> SaveCountToKeepConfig { get; private set; }

		public int BackupIntervalInMinutes { get; private set; }

		public int SaveCountToKeep { get; private set; }

		public bool IsInGame { get; private set; }

		public TimeSpan AutosaveInterval => TimeSpan.FromMinutes(BackupIntervalInMinutes);

		public bool DetectedMoreBankTabsMod { get; private set; } = false;


		private string ObsoleteModDataFolderPath => Path.Combine(ProfileDataManager._current._dataPath, ModDataFolderName);

		private string ModDataFolderPath => Path.Combine(Path.GetDirectoryName(Paths.ExecutablePath), ModDataFolderName);

		private string CharacterFolderPath => Path.Combine(ModDataFolderPath, "Characters");

		private string ItemBankFolderPath => Path.Combine(ModDataFolderPath, "ItemBank");

		private string MultiSavesFolderPath => Path.Combine(ModDataFolderPath, "Multi");

		public string SanitizedCurrentTime
		{
			get
			{
				string text = DateTime.UtcNow.ToString("yyyy:MM:dd-HH:mm:ss", CultureInfo.InvariantCulture);
				for (int i = 0; i < BannedChars.Length; i++)
				{
					text = text.Replace($"{BannedChars[i]}", "_");
				}
				return text;
			}
		}

		public AutoSaver()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			char[] invalidPathChars = Path.GetInvalidPathChars();
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			int num = 0;
			char[] array = new char[invalidPathChars.Length + invalidFileNameChars.Length];
			ReadOnlySpan<char> readOnlySpan = new ReadOnlySpan<char>(invalidPathChars);
			readOnlySpan.CopyTo(new Span<char>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			ReadOnlySpan<char> readOnlySpan2 = new ReadOnlySpan<char>(invalidFileNameChars);
			readOnlySpan2.CopyTo(new Span<char>(array).Slice(num, readOnlySpan2.Length));
			num += readOnlySpan2.Length;
			BannedChars = array;
			ModDataFolderName = "Marioalexsan_AutoSaver";
			_checkedForOldAutosaverBackups = false;
			((BaseUnityPlugin)this)..ctor();
			_plugin = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("Marioalexsan.AutoSaver");
			EnableAutosaving = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableAutosaving", true, "True to enable autosaving every few minutes, false to disable it.");
			SaveOnMapChange = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SaveOnMapChange", false, "Set to true to trigger autosaving whenever a new level is loaded.");
			AppendSlotToSaveName = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AppendSlotToSaveName", true, "Set to true to append slot index to the saved character names, false to use the character name only. Recommended if you use characters with duplicate names.");
			BackupIntervalInMinutesConfig = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BackupInterval", 4, new ConfigDescription("Interval between save backups, in minutes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
			SaveCountToKeepConfig = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SavesToKeep", 15, new ConfigDescription("Maximum number of saves to keep.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 50), Array.Empty<object>()));
			BackupIntervalInMinutes = BackupIntervalInMinutesConfig.Value;
			SaveCountToKeep = SaveCountToKeepConfig.Value;
			EnableExperimentalFeatures = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableExperimentalFeatures", false, "Set to true to enable experimental features.");
			SaveMultiplayerKeyCode = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Experimental", "SaveMultiplayerKeyCode", (KeyCode)270, "Key to trigger saving other people's saves in multiplayer under the \"Multi\" folder." + Environment.NewLine + "Note that saves saved in this way are lackluster.");
		}

		private void Awake()
		{
			_harmony.PatchAll();
			InitializeConfiguration();
			Logging.LogInfo("AutoSaver initialized!");
		}

		private void CheckForOldAutosaverBackups()
		{
			if (!Directory.Exists(ObsoleteModDataFolderPath))
			{
				return;
			}
			if (Directory.Exists(ModDataFolderPath))
			{
				Logging.LogWarning("Found old Autosaver folder in " + ObsoleteModDataFolderPath + ", but new save location " + ModDataFolderPath + " already exists.");
				Logging.LogWarning("Please backup and move " + ObsoleteModDataFolderPath + " out of the profileCollections folder manually!");
				return;
			}
			Logging.LogInfo("Found old Autosaver folder in " + ObsoleteModDataFolderPath + ", will try to move it to the new save location " + ModDataFolderPath + ".");
			try
			{
				Directory.Move(ObsoleteModDataFolderPath, ModDataFolderPath);
				Logging.LogInfo("Backup data moved successfully to the new location!");
			}
			catch (Exception ex)
			{
				Logging.LogError("Failed to move old backup folder! Please send the exception message to the mod developer:");
				Logging.LogError(ex.ToString());
				Logging.LogError("Please check " + ObsoleteModDataFolderPath + " and backup and move it out of the profileCollections folder manually!");
			}
		}

		private void InitializeConfiguration()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (!EasySettings.IsAvailable)
			{
				return;
			}
			EasySettings.OnApplySettings.AddListener((UnityAction)delegate
			{
				try
				{
					((BaseUnityPlugin)this).Config.Save();
					BackupIntervalInMinutes = BackupIntervalInMinutesConfig.Value;
					SaveCountToKeep = SaveCountToKeepConfig.Value;
				}
				catch (Exception ex)
				{
					Logging.LogError("AutoSaevr crashed in OnApplySettings! Please report this error to the mod developer:");
					Logging.LogError(ex.ToString());
				}
			});
			EasySettings.OnInitialized.AddListener((UnityAction)delegate
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Expected O, but got Unknown
				EasySettings.AddHeader("AutoSaver");
				EasySettings.AddToggle("Enable periodic autosaves", EnableAutosaving);
				EasySettings.AddToggle("Enable autosaving whenever map changes", SaveOnMapChange);
				EasySettings.AddToggle("Append save slot to save names (recommended)", AppendSlotToSaveName);
				EasySettings.AddAdvancedSlider("Backup interval (minutes)", BackupIntervalInMinutesConfig);
				EasySettings.AddAdvancedSlider("Number of saves to keep", SaveCountToKeepConfig);
				EasySettings.AddButton("Open save backups folder", (UnityAction)delegate
				{
					Application.OpenURL(new Uri(ModDataFolderPath ?? "").AbsoluteUri);
				});
			});
		}

		internal void GameEntered()
		{
			bool flag = false;
			if (!IsInGame)
			{
				IsInGame = true;
				flag = true;
				Logging.LogInfo("Game entered. Activating character autosaves.");
			}
			else if (SaveOnMapChange.Value)
			{
				flag = true;
				Logging.LogInfo("Map changed. Autosaving.");
			}
			if (flag)
			{
				ProfileDataManager._current.Load_ItemStorageData();
				RunAutosaves();
			}
		}

		internal void GameExited()
		{
			Logging.LogInfo("Game exited. Stopping character autosaves.");
			RunAutosaves();
			IsInGame = false;
		}

		private void Update()
		{
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			if (!_checkedForOldAutosaverBackups && ProfileDataManager._current?._dataPath != null)
			{
				_checkedForOldAutosaverBackups = true;
				CheckForOldAutosaverBackups();
			}
			if (!DetectedMoreBankTabsMod && Chainloader.PluginInfos.ContainsKey("com.16mb.morebanktabs"))
			{
				DetectedMoreBankTabsMod = true;
				Logging.LogInfo("Detected MoreBankTabs mod (com.16mb.morebanktabs).");
				Logging.LogInfo("Will try to backup the extra bank tabs.");
			}
			if (IsInGame)
			{
				_elapsedAutosaveTime += TimeSpan.FromSeconds(Time.deltaTime);
				if (EnableAutosaving.Value && _elapsedAutosaveTime >= AutosaveInterval)
				{
					Logging.LogInfo($"Periodic autosave triggered ({AutosaveInterval.TotalMinutes} minutes have passed).");
					RunAutosaves();
				}
				if (!CharacterAutoSaver.SaveDone)
				{
					AutosaveCurrentCharacter();
				}
				if (!ItemBankAutoSaver.SaveDone)
				{
					AutosaveCurrentItemBank();
				}
			}
			if (!EnableExperimentalFeatures.Value || !Input.GetKeyDown(SaveMultiplayerKeyCode.Value))
			{
				return;
			}
			Logging.LogInfo("[Experimental] Saving every online player's saves.");
			Player[] array = Object.FindObjectsOfType<Player>();
			foreach (Player val in array)
			{
				Logging.LogInfo("Saving player data for " + val._nickname);
				Directory.CreateDirectory(MultiSavesFolderPath);
				CharacterAutoSaver.TrySaveSpecificProfileToLocation(val, Path.Combine(MultiSavesFolderPath, SanitizePlayerName(val)));
				if (!CharacterAutoSaver.SaveDone)
				{
					Logging.LogWarning($"Failed to do save for {val._nickname}. Current game status is {val._currentGameCondition}.");
				}
			}
		}

		private void RunAutosaves()
		{
			_elapsedAutosaveTime = TimeSpan.Zero;
			AutosaveCurrentCharacter();
			AutosaveCurrentItemBank();
		}

		public string SanitizePlayerName(Player player)
		{
			string text = player._nickname;
			for (int i = 0; i < BannedChars.Length; i++)
			{
				int num = char.ConvertToUtf32($"{BannedChars[i]}", 0);
				text = text.Replace($"{BannedChars[i]}", $"_{num}");
			}
			return text;
		}

		public string GetBackupNameForCurrentPlayer()
		{
			if (AppendSlotToSaveName.Value)
			{
				return $"{SanitizePlayerName(Player._mainPlayer)}_slot{ProfileDataManager._current._selectedFileIndex}";
			}
			return SanitizePlayerName(Player._mainPlayer) ?? "";
		}

		private void RunItemBankGarbageCollector()
		{
			if (!Directory.Exists(ItemBankFolderPath))
			{
				Logging.LogWarning("Couldn't find backup path " + ItemBankFolderPath + " to run garbage collection for.");
				return;
			}
			List<string> list = new List<string>();
			foreach (string item in Directory.EnumerateDirectories(ItemBankFolderPath))
			{
				list.Add(Path.GetFileName(item));
			}
			list.Remove("_latest");
			list.Sort();
			while (list.Count > SaveCountToKeep)
			{
				string path = list[0];
				list.RemoveAt(0);
				string text = Path.Combine(ItemBankFolderPath, path);
				if (!text.Contains(ModDataFolderName))
				{
					throw new InvalidOperationException("Got an invalid folder to delete " + text + ", please notify the mod developer!");
				}
				Directory.Delete(Path.Combine(ItemBankFolderPath, path), recursive: true);
			}
		}

		private void RunCharacterGarbageCollector()
		{
			string text = Path.Combine(CharacterFolderPath, GetBackupNameForCurrentPlayer());
			if (!Directory.Exists(text))
			{
				Logging.LogWarning("Couldn't find backup path " + text + " to run garbage collection for.");
				return;
			}
			List<string> list = new List<string>();
			foreach (string item in Directory.EnumerateFiles(text))
			{
				list.Add(Path.GetFileName(item));
			}
			list.Remove("_latest");
			list.Sort();
			while (list.Count > SaveCountToKeep)
			{
				string path = list[0];
				list.RemoveAt(0);
				string text2 = Path.Combine(CharacterFolderPath, GetBackupNameForCurrentPlayer(), path);
				if (!text2.Contains(ModDataFolderName))
				{
					throw new InvalidOperationException("Got an invalid file to delete " + text2 + ", please notify the mod developer!");
				}
				File.Delete(text2);
			}
		}

		private void AutosaveCurrentItemBank()
		{
			try
			{
				Directory.CreateDirectory(ModDataFolderPath);
				string text = Path.Combine(ItemBankFolderPath, SanitizedCurrentTime);
				Directory.CreateDirectory(text);
				ItemBankAutoSaver.TrySaveCurrentProfileToLocation(text);
				if (ItemBankAutoSaver.SaveDone)
				{
					if (DetectedMoreBankTabsMod)
					{
						ItemBankAutoSaver.SaveModBankTabsToLocation(text);
					}
					string text2 = Path.Combine(ItemBankFolderPath, "_latest");
					Directory.CreateDirectory(text2);
					foreach (string item in Directory.EnumerateFiles(text))
					{
						File.Copy(item, Path.Combine(text2, Path.GetFileName(item)), overwrite: true);
					}
				}
				RunItemBankGarbageCollector();
			}
			catch (Exception arg)
			{
				Logging.LogError("Failed to autosave!");
				Logging.LogError($"Exception message: {arg}");
			}
		}

		private void AutosaveCurrentCharacter()
		{
			try
			{
				if (!Object.op_Implicit((Object)(object)Player._mainPlayer))
				{
					Logging.LogError("Couldn't autosave! No main player found.");
					return;
				}
				Directory.CreateDirectory(ModDataFolderPath);
				string text = Path.Combine(CharacterFolderPath, GetBackupNameForCurrentPlayer());
				Directory.CreateDirectory(text);
				string text2 = Path.Combine(text, SanitizedCurrentTime);
				CharacterAutoSaver.TrySaveCurrentProfileToLocation(text2);
				if (CharacterAutoSaver.SaveDone)
				{
					File.Copy(text2, Path.Combine(text, "_latest"), overwrite: true);
				}
				RunCharacterGarbageCollector();
			}
			catch (Exception arg)
			{
				Logging.LogError("Couldn't autosave!");
				Logging.LogError($"Exception message: {arg}");
			}
		}
	}
	internal static class Logging
	{
		private static ManualLogSource InternalLogger => AutoSaver.Plugin.Logger;

		public static void LogFatal(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)1, toggle);
		}

		public static void LogError(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)2, toggle);
		}

		public static void LogWarning(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)4, toggle);
		}

		public static void LogMessage(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)8, toggle);
		}

		public static void LogInfo(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)16, toggle);
		}

		public static void LogDebug(object data, ConfigEntry<bool>? toggle = null)
		{
			Log(data, (LogLevel)32, toggle);
		}

		private static void Log(object data, LogLevel level = 16, ConfigEntry<bool>? toggle = null)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (toggle == null || toggle.Value)
			{
				ManualLogSource internalLogger = InternalLogger;
				if (internalLogger != null)
				{
					internalLogger.Log(level, data);
				}
			}
		}
	}
	internal static class ModInfo
	{
		public const string PLUGIN_GUID = "Marioalexsan.AutoSaver";

		public const string PLUGIN_NAME = "AutoSaver";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}
namespace Marioalexsan.AutoSaver.SoftDependencies
{
	public static class EasySettings
	{
		private const MethodImplOptions SoftDepend = MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization;

		public const string ModID = "EasySettings";

		public static readonly Version ExpectedVersion = new Version("1.1.6");

		private static BaseUnityPlugin? _plugin;

		private static bool _initialized;

		public static bool IsAvailable
		{
			get
			{
				if (!_initialized)
				{
					_plugin = (Chainloader.PluginInfos.TryGetValue("EasySettings", out var value) ? value.Instance : null);
					_initialized = true;
					if ((Object)(object)_plugin == (Object)null)
					{
						Logging.LogWarning("Soft dependency EasySettings was not found.");
					}
					else if (_plugin.Info.Metadata.Version != ExpectedVersion)
					{
						Logging.LogWarning(string.Format("Soft dependency {0} has a different version than expected (have: {1}, expect: {2}).", "EasySettings", _plugin.Info.Metadata.Version, ExpectedVersion));
					}
				}
				return (Object)(object)_plugin != (Object)null;
			}
		}

		public static UnityEvent OnInitialized
		{
			[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
			get
			{
				return Settings.OnInitialized;
			}
		}

		public static UnityEvent OnCancelSettings
		{
			[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
			get
			{
				return Settings.OnCancelSettings;
			}
		}

		public static UnityEvent OnApplySettings
		{
			[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
			get
			{
				return Settings.OnApplySettings;
			}
		}

		public static UnityEvent OnCloseSettings
		{
			[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
			get
			{
				return Settings.OnCloseSettings;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddSpace()
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddSpace()).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddHeader(string label)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddHeader(label)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddButton(string buttonLabel, UnityAction onClick)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddButton(buttonLabel, onClick)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddToggle(string label, ConfigEntry<bool> config)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddToggle(label, config)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddSlider(string label, ConfigEntry<float> config, bool wholeNumbers = false)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddSlider(label, config, wholeNumbers)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddAdvancedSlider(string label, ConfigEntry<float> config, bool wholeNumbers = false)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddAdvancedSlider(label, config, wholeNumbers)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddAdvancedSlider(string label, ConfigEntry<int> config)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddAdvancedSlider(label, config)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddDropdown<T>(string label, ConfigEntry<T> config) where T : Enum
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddDropdown<T>(label, config)).Root).gameObject;
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static GameObject AddKeyButton(string label, ConfigEntry<KeyCode> config)
		{
			return ((Component)((BaseAtlyssElement)Settings.ModTab.AddKeyButton(label, config)).Root).gameObject;
		}
	}
}
namespace Marioalexsan.AutoSaver.HarmonyReversePatches
{
	[HarmonyPatch(typeof(ProfileDataManager), "Save_ProfileData")]
	internal static class CharacterAutoSaver
	{
		private static string? SaveLocationOverride;

		private static string? TempContents;

		private static Player? TargetPlayer;

		internal static bool SaveDone { get; private set; } = true;


		public static void TrySaveCurrentProfileToLocation(string location)
		{
			if (SaveDone)
			{
				AutoSaver.Plugin.Logger.LogInfo((object)"Triggering character save process...");
			}
			SaveLocationOverride = location;
			SaveDone = false;
			TargetPlayer = Player._mainPlayer;
			SaveProfileData(ProfileDataManager._current);
		}

		public static void TrySaveSpecificProfileToLocation(Player player, string location)
		{
			if (SaveDone)
			{
				AutoSaver.Plugin.Logger.LogInfo((object)"Triggering character save process...");
			}
			SaveLocationOverride = location;
			SaveDone = false;
			TargetPlayer = player;
			SaveProfileData(ProfileDataManager._current);
		}

		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPriority(0)]
		private static void SaveProfileData(ProfileDataManager __instance)
		{
			Transpiler(null);
			throw new NotImplementedException("Stub method");
			static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> data)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Expected O, but got Unknown
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Expected O, but got Unknown
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Expected O, but got Unknown
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Expected O, but got Unknown
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Expected O, but got Unknown
				//IL_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Expected O, but got Unknown
				//IL_0151: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Expected O, but got Unknown
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f5: Expected O, but got Unknown
				//IL_0244: Unknown result type (might be due to invalid IL or missing references)
				//IL_0250: Expected O, but got Unknown
				CodeMatcher val = new CodeMatcher(data, (ILGenerator)null);
				int num = 0;
				while (true)
				{
					val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
					{
						new CodeMatch((OpCode?)OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => File.WriteAllText(null, null))), (string)null)
					});
					if (val.IsInvalid)
					{
						break;
					}
					num++;
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[5]
					{
						new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.Field(typeof(CharacterAutoSaver), "TempContents")),
						new CodeInstruction(OpCodes.Pop, (object)null),
						new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(CharacterAutoSaver), "SaveLocationOverride")),
						new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => MarkSaveDone(null)))),
						new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(CharacterAutoSaver), "TempContents"))
					});
					val.Advance(1);
				}
				if (num != 2)
				{
					AutoSaver.Plugin.Logger.LogWarning((object)$"WARNING: CharacterAutoSaver expected {2} patch locations, got {num}.");
					AutoSaver.Plugin.Logger.LogWarning((object)"Either the vanilla code changed, or mods added extra stuff. This may or may not cause issues.");
				}
				val.Start();
				num = 0;
				while (true)
				{
					val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
					{
						new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Player), "_mainPlayer"), (string)null)
					});
					if (val.IsInvalid)
					{
						break;
					}
					List<Label> list = val.Instruction.labels.ToList();
					val.RemoveInstruction();
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(CharacterAutoSaver), "TargetPlayer")), (IEnumerable<Label>)list) });
					num++;
				}
				AutoSaver.Plugin.Logger.LogInfo((object)$"Patched {num} instances of Player._mainPlayer.");
				return val.InstructionEnumeration();
			}
		}

		private static string MarkSaveDone(string location)
		{
			SaveDone = true;
			return location;
		}
	}
	[HarmonyPatch(typeof(ProfileDataManager), "Save_ItemStorageData")]
	internal static class ItemBankAutoSaver
	{
		private static string? SaveLocationOverride;

		private static string? TempContents;

		private static int BanksDone = 0;

		private static int BanksMax = 0;

		internal static bool SaveDone { get; private set; } = true;


		public static void TrySaveCurrentProfileToLocation(string location)
		{
			if (SaveDone)
			{
				AutoSaver.Plugin.Logger.LogInfo((object)"Triggering item bank save process...");
			}
			SaveLocationOverride = location;
			BanksDone = 0;
			SaveDone = false;
			SaveProfileData(ProfileDataManager._current);
		}

		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPriority(0)]
		private static void SaveProfileData(ProfileDataManager __instance)
		{
			Transpiler(null);
			throw new NotImplementedException("Stub method");
			static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> data)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Expected O, but got Unknown
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Expected O, but got Unknown
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Expected O, but got Unknown
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Expected O, but got Unknown
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Expected O, but got Unknown
				//IL_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Expected O, but got Unknown
				//IL_0151: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Expected O, but got Unknown
				CodeMatcher val = new CodeMatcher(data, (ILGenerator)null);
				int num = 0;
				while (true)
				{
					val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
					{
						new CodeMatch((OpCode?)OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => File.WriteAllText(null, null))), (string)null)
					});
					if (val.IsInvalid)
					{
						break;
					}
					num++;
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[5]
					{
						new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.Field(typeof(ItemBankAutoSaver), "TempContents")),
						new CodeInstruction(OpCodes.Pop, (object)null),
						new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ItemBankAutoSaver), "SaveLocationOverride")),
						new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo((Expression<Action>)(() => MarkSaveDone(null)))),
						new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ItemBankAutoSaver), "TempContents"))
					});
					val.Advance(1);
				}
				if (num != 3)
				{
					AutoSaver.Plugin.Logger.LogWarning((object)$"WARNING: ItemBankAutoSaver expected {3} patch locations, got {num}.");
					AutoSaver.Plugin.Logger.LogWarning((object)"Either the vanilla code changed, or mods added extra stuff. This may or may not cause issues.");
				}
				BanksMax = 3;
				return val.InstructionEnumeration();
			}
		}

		private static string MarkSaveDone(string location)
		{
			BanksDone++;
			if (BanksDone >= BanksMax)
			{
				SaveDone = true;
			}
			return Path.Combine(location, $"itembank_{BanksDone - 1}");
		}

		public static void SaveModBankTabsToLocation(string location)
		{
			try
			{
				AutoSaver.Plugin.Logger.LogInfo((object)"Attempting to save MoreBankTabs data...");
				BaseUnityPlugin instance = Chainloader.PluginInfos["com.16mb.morebanktabs"].Instance;
				object value = AccessTools.Field(((object)instance).GetType(), "_itemStorageProfile_03").GetValue(instance);
				object value2 = AccessTools.Field(((object)instance).GetType(), "_itemStorageProfile_04").GetValue(instance);
				object value3 = AccessTools.Field(((object)instance).GetType(), "_itemStorageProfile_05").GetValue(instance);
				object value4 = AccessTools.Field(((object)instance).GetType(), "_itemDatas_03").GetValue(instance);
				object value5 = AccessTools.Field(((object)instance).GetType(), "_itemDatas_04").GetValue(instance);
				object value6 = AccessTools.Field(((object)instance).GetType(), "_itemDatas_05").GetValue(instance);
				object value7 = AccessTools.Method(value4.GetType(), "ToArray", (Type[])null, (Type[])null).Invoke(value4, Array.Empty<object>());
				object value8 = AccessTools.Method(value5.GetType(), "ToArray", (Type[])null, (Type[])null).Invoke(value5, Array.Empty<object>());
				object value9 = AccessTools.Method(value6.GetType(), "ToArray", (Type[])null, (Type[])null).Invoke(value6, Array.Empty<object>());
				AccessTools.Field(value.GetType(), "_heldItemStorage").SetValue(value, value7);
				AccessTools.Field(value2.GetType(), "_heldItemStorage").SetValue(value2, value8);
				AccessTools.Field(value3.GetType(), "_heldItemStorage").SetValue(value3, value9);
				string contents = JsonUtility.ToJson(value, true);
				string contents2 = JsonUtility.ToJson(value2, true);
				string contents3 = JsonUtility.ToJson(value3, true);
				File.WriteAllText(Path.Combine(location, "MoreBankTabs_itemBank_03"), contents);
				File.WriteAllText(Path.Combine(location, "MoreBankTabs_itemBank_04"), contents2);
				File.WriteAllText(Path.Combine(location, "MoreBankTabs_itemBank_05"), contents3);
				AutoSaver.Plugin.Logger.LogInfo((object)"MoreBankTabs slots saved.");
			}
			catch (Exception arg)
			{
				AutoSaver.Plugin.Logger.LogError((object)"Failed to save MoreBankTabs info.");
				AutoSaver.Plugin.Logger.LogError((object)$"Exception info: {arg}");
			}
		}
	}
}
namespace Marioalexsan.AutoSaver.HarmonyPatches
{
	[HarmonyPatch]
	internal static class InGameUI_Init_SaveQuitGame
	{
		private static MethodInfo TargetMethod()
		{
			string version = Application.version;
			if (1 == 0)
			{
			}
			MethodInfo result = ((version == "Beta 1.6.2b") ? AccessTools.Method("InGameUI:Init_SaveQuitGame", (Type[])null, (Type[])null) : ((!(version == "Beta 2.0.5d")) ? AccessTools.Method("OptionsMenuCell:Init_SaveQuitGame", (Type[])null, (Type[])null) : AccessTools.Method("OptionsMenuCell:Init_SaveQuitGame", (Type[])null, (Type[])null)));
			if (1 == 0)
			{
			}
			return result;
		}

		private static void Prefix()
		{
			AutoSaver.Plugin.GameExited();
		}
	}
	[HarmonyPatch(typeof(Player), "OnPlayerMapInstanceChange")]
	internal static class Player_OnPlayerMapInstanceChange
	{
		private static void Postfix(Player __instance, MapInstance _new)
		{
			if ((Object)(object)__instance == (Object)(object)Player._mainPlayer)
			{
				AutoSaver.Plugin.GameEntered();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}