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 FixedBankTabs;
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: IgnoresAccessChecksTo("MoreBankTabsFixed")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Marioalexsan.AutoSaver")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+ae13d0a34b777c75e3845c152643952898a0a136")]
[assembly: AssemblyProduct("AutoSaver")]
[assembly: AssemblyTitle("Marioalexsan.AutoSaver")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.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.4.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class AutoSaver : BaseUnityPlugin
{
public const string MoreBankTabsFixedIdentifier = "MoreBankTabsFixed";
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> SaveOnManualSave { 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);
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");
private string GameVersion => Application.version;
public string SanitizedCurrentTime => SanitizeStringSimple(DateTime.UtcNow.ToString("yyyy:MM:dd-HH:mm:ss", CultureInfo.InvariantCulture));
public AutoSaver()
{
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Expected O, but got Unknown
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Expected O, but got Unknown
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Expected O, but got Unknown
char[] invalidPathChars = Path.GetInvalidPathChars();
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
int num = 0;
char[] array = new char[1 + (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;
array[num] = '.';
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.");
SaveOnManualSave = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SaveOnManualSave", true, "Set to true to trigger autosaving whenever you manually save from the menu.");
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("AutoSaver crashed in OnApplySettings! Please report this error to the mod developer:");
Logging.LogError(ex.ToString());
}
});
EasySettings.OnInitialized.AddListener((UnityAction)delegate
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
EasySettings.AddHeader("AutoSaver");
EasySettings.AddToggle("Enable periodic autosaves", EnableAutosaving);
EasySettings.AddToggle("Enable autosaving whenever map changes", SaveOnMapChange);
EasySettings.AddToggle("Enable backups when saving in the menu", SaveOnManualSave);
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 ManualSaveTriggered()
{
if (IsInGame && SaveOnManualSave.Value)
{
Logging.LogInfo("Manual save triggered.");
RunAutosaves();
}
}
internal void GameExited()
{
Logging.LogInfo("Game exited. Stopping character autosaves.");
RunAutosaves();
IsInGame = false;
}
private void Update()
{
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
if (!_checkedForOldAutosaverBackups && ProfileDataManager._current?._dataPath != null)
{
_checkedForOldAutosaverBackups = true;
CheckForOldAutosaverBackups();
}
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, SanitizeString(val._nickname)));
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 SanitizeStringSimple(string str)
{
for (int i = 0; i < BannedChars.Length; i++)
{
str = str.Replace($"{BannedChars[i]}", "_");
}
return str;
}
public string SanitizeString(string str)
{
for (int i = 0; i < BannedChars.Length; i++)
{
int num = char.ConvertToUtf32($"{BannedChars[i]}", 0);
str = str.Replace($"{BannedChars[i]}", $"_{num}");
}
return str;
}
public string GetBackupNameForCurrentPlayer()
{
if (AppendSlotToSaveName.Value)
{
return $"{SanitizeString(Player._mainPlayer._nickname)}_slot{ProfileDataManager._current._selectedFileIndex}";
}
return SanitizeString(Player._mainPlayer._nickname) ?? "";
}
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.RemoveAll((string x) => x.Contains("_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.RemoveAll((string x) => x.Contains("_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 itembankFolder = Path.Combine(ItemBankFolderPath, SanitizedCurrentTime);
Directory.CreateDirectory(itembankFolder);
ItemBankAutoSaver.TrySaveCurrentProfileToLocation(itembankFolder);
if (ItemBankAutoSaver.SaveDone)
{
if (MoreBankTabsFixed.IsAvailable)
{
ItemBankAutoSaver.SaveExtraBankTabsToLocation(itembankFolder);
}
CopySaves("_latest");
CopySaves("_latest_version_" + SanitizeStringSimple(GameVersion));
}
RunItemBankGarbageCollector();
void CopySaves(string saveName)
{
string text = Path.Combine(ItemBankFolderPath, saveName);
Directory.CreateDirectory(text);
foreach (string item in Directory.EnumerateFiles(itembankFolder))
{
File.Copy(item, Path.Combine(text, Path.GetFileName(item)), overwrite: true);
}
}
}
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);
File.Copy(text2, Path.Combine(text, "_latest_version_" + SanitizeStringSimple(GameVersion)), 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 GUID = "Marioalexsan.AutoSaver";
public const string NAME = "AutoSaver";
public const string VERSION = "1.4.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.8");
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;
}
}
public static class MoreBankTabsFixed
{
private const MethodImplOptions SoftDepend = MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization;
public const string ModID = "MoreBankTabsFixed";
public static readonly Version ExpectedVersion = new Version("1.0.0");
private static BaseUnityPlugin? _plugin;
private static bool _initialized;
public static bool IsAvailable
{
get
{
if (!_initialized)
{
_plugin = (Chainloader.PluginInfos.TryGetValue("MoreBankTabsFixed", out var value) ? value.Instance : null);
_initialized = true;
if ((Object)(object)_plugin == (Object)null)
{
Logging.LogWarning("Soft dependency MoreBankTabsFixed 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}).", "MoreBankTabsFixed", _plugin.Info.Metadata.Version, ExpectedVersion));
}
}
return (Object)(object)_plugin != (Object)null;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static ItemStorage_Profile[] GetExtraProfiles()
{
return BankPatches.newItemStorageProfiles;
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static List<ItemData>[] GetItemDatas()
{
return BankPatches.newItemDatas;
}
}
}
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 SaveExtraBankTabsToLocation(string location)
{
try
{
AutoSaver.Plugin.Logger.LogInfo((object)"Attempting to save MoreBankTabsFixed data...");
ItemStorage_Profile[] extraProfiles = MoreBankTabsFixed.GetExtraProfiles();
List<ItemData>[] itemDatas = MoreBankTabsFixed.GetItemDatas();
for (int i = 0; i < extraProfiles.Length; i++)
{
if (extraProfiles[i] != null)
{
extraProfiles[i]._heldItemStorage = itemDatas[i].ToArray();
string contents = JsonUtility.ToJson((object)extraProfiles[i], true);
File.WriteAllText(Path.Combine(location, $"MoreBankTabsFixed_itemBank_{i + 3}"), contents);
}
}
AutoSaver.Plugin.Logger.LogInfo((object)$"MoreBankTabsFixed slots saved ({extraProfiles.Length} total).");
}
catch (Exception arg)
{
AutoSaver.Plugin.Logger.LogError((object)"Failed to save MoreBankTabsFixed 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]
internal static class OptionsMenuCell_SaveFile_Routine
{
private static MethodInfo TargetMethod()
{
return typeof(OptionsMenuCell).Assembly.DefinedTypes.First((TypeInfo x) => x.Name.Contains("SaveFile_Routine")).DeclaredMethods.First((MethodInfo x) => x.Name == "MoveNext");
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> code)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(code, (ILGenerator)null);
val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction ins) => CodeInstructionExtensions.Calls(ins, AccessTools.Method(typeof(ProfileDataManager), "Save_ProfileData", (Type[])null, (Type[])null))), (string)null)
});
if (val.IsInvalid)
{
AutoSaver.Plugin.Logger.LogWarning((object)"WARNING: OptionsMenuCell_SaveFile_Routine couldn't find call to Save_ProfileData!");
AutoSaver.Plugin.Logger.LogWarning((object)"Either the vanilla code changed, or mods added extra stuff. Backing up on manual saves will not work due to this.");
return code;
}
val.Advance(1);
List<Label> list = CodeInstructionExtensions.ExtractLabels(val.Instruction);
val.Insert((CodeInstruction[])(object)new CodeInstruction[1] { CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptionsMenuCell_SaveFile_Routine), "ManualSaveTriggered", (Type[])null, (Type[])null)), (IEnumerable<Label>)list) });
return val.InstructionEnumeration();
}
private static void ManualSaveTriggered()
{
AutoSaver.Plugin.ManualSaveTriggered();
}
}
[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)
{
}
}
}