Decompiled source of MoreSaveSlots v1.0.0

MoreSaveSlots/MoreSaveSlots.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("MoreSaveSlots")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("raddude")]
[assembly: AssemblyProduct("MoreSaveSlots")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(true)]
[assembly: Guid("071994df-c696-4ece-ad36-48d4036214b5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace MoreSaveSlots;

internal class Configs
{
	internal static ConfigEntry<int> numPages;

	internal static void InitializeConfigs()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		ConfigFile config = ((BaseUnityPlugin)MSS_Plugin.Instance).Config;
		numPages = config.Bind<int>("Settings", "Number of save slot pages<br>(must restart game)", 3, new ConfigDescription("The number of pages of save slots. Each page has 6 slots.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
	}
}
internal static class Extensions
{
	public static T GetPrivateField<T>(this object obj, string field)
	{
		return (T)Traverse.Create(obj).Field(field).GetValue();
	}

	public static void SetPrivateField(this object obj, string field, object value)
	{
		Traverse.Create(obj).Field(field).SetValue(value);
	}

	public static void SetPrivateField<T>(string field, object value)
	{
		Traverse.Create(typeof(T)).Field(field).SetValue(value);
	}

	public static object InvokePrivateMethod(this object obj, string method, params object[] parameters)
	{
		return AccessTools.Method(obj.GetType(), method, (Type[])null, (Type[])null).Invoke(obj, parameters);
	}
}
[BepInPlugin("com.raddude.moresaveslots", "MoreSaveSlots", "1.0.0")]
public class MSS_Plugin : BaseUnityPlugin
{
	public const string PLUGIN_GUID = "com.raddude.moresaveslots";

	public const string PLUGIN_NAME = "MoreSaveSlots";

	public const string PLUGIN_VERSION = "1.0.0";

	private static ManualLogSource _logger;

	internal static MSS_Plugin Instance { get; private set; }

	internal static void LogDebug(string message)
	{
		_logger.LogDebug((object)message);
	}

	internal static void LogInfo(string message)
	{
		_logger.LogInfo((object)message);
	}

	internal static void LogWarning(string message)
	{
		_logger.LogWarning((object)message);
	}

	internal static void LogError(string message)
	{
		_logger.LogError((object)message);
	}

	private void Awake()
	{
		if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		Instance = this;
		_logger = ((BaseUnityPlugin)this).Logger;
		Configs.InitializeConfigs();
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.raddude.moresaveslots");
	}
}
internal class Paginator
{
	internal const int SLOTS_PER_PAGE = 6;

	private static int _currentPage = 0;

	private static readonly List<GameObject> _allSlotRoots = new List<GameObject>();

	private static BackupSavesListUI _backUpSavesListUI;

	public static void AddMoreSaveSlots(BackupSavesListUI backupSavesListUI, StartMenuButton[] existingButtons)
	{
		_backUpSavesListUI = backupSavesListUI;
		List<StartMenuButton> list = (from b in existingButtons
			where (int)b.GetPrivateField<StartMenuButtonType>("type") == 8
			orderby b.saveSlot
			select b).ToList();
		foreach (StartMenuButton item in list)
		{
			_allSlotRoots.Add(((Component)((Component)item).transform.parent).gameObject);
		}
		for (int i = 6; i < 6 * Configs.numPages.Value; i++)
		{
			int index = i % 6;
			GameObject val = _allSlotRoots[index];
			GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent);
			((Object)val2).name = $"SaveSlot_{i}";
			StartMenuButton componentInChildren = val2.GetComponentInChildren<StartMenuButton>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.saveSlot = i;
				RefreshSlotText(componentInChildren);
			}
			val2.SetActive(false);
			_allSlotRoots.Add(val2);
		}
	}

	private static void RefreshSlotText(StartMenuButton btn)
	{
		if (SaveSlots.slotsActive != null && btn.saveSlot < SaveSlots.slotsActive.Length && SaveSlots.slotsActive[btn.saveSlot])
		{
			DateTime lastWriteTime = File.GetLastWriteTime(SaveSlots.GetSlotSavePath(btn.saveSlot));
			btn.SetButtonText(lastWriteTime.ToShortTimeString() + "\n" + lastWriteTime.ToShortDateString());
		}
		else
		{
			btn.SetButtonText("(empty)");
		}
	}

	public static bool ButtonClick(StartMenuButtonType button)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Invalid comparison between Unknown and I4
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		if ((int)button == 13)
		{
			_backUpSavesListUI.HideList();
			_currentPage = Mathf.Max(0, _currentPage - 1);
			SaveSlotsUI.UpdatePageNumText(_currentPage);
			ShowPage(_currentPage);
			return false;
		}
		if ((int)button == 14)
		{
			_backUpSavesListUI.HideList();
			_currentPage = Mathf.Min(Configs.numPages.Value - 1, _currentPage + 1);
			SaveSlotsUI.UpdatePageNumText(_currentPage);
			ShowPage(_currentPage);
			return false;
		}
		return true;
	}

	private static void ShowPage(int page)
	{
		foreach (GameObject allSlotRoot in _allSlotRoots)
		{
			allSlotRoot.SetActive(false);
		}
		_currentPage = page;
		int num = page * 6;
		int num2 = Mathf.Min(num + 6, 6 * Configs.numPages.Value);
		for (int i = num; i < num2; i++)
		{
			_allSlotRoots[i].SetActive(true);
		}
	}
}
internal class SaveMenuPatches
{
	[HarmonyPatch(typeof(SaveSlots), "Awake")]
	private class SaveSlotsPatches
	{
		public static bool Prefix()
		{
			SaveSlots.slotsActive = new bool[6 * Configs.numPages.Value];
			for (int i = 0; i < SaveSlots.slotsActive.Length; i++)
			{
				SaveSlots.currentSlot = i;
				if (File.Exists(SaveSlots.GetCurrentSavePath()))
				{
					SaveSlots.slotsActive[i] = true;
					SaveSlots.activeSlotsCount++;
				}
			}
			MSS_Plugin.LogDebug("SaveSlots: activeSlotsCount is " + SaveSlots.activeSlotsCount);
			return false;
		}
	}

	[HarmonyPatch(typeof(StartMenu))]
	private class StartMenuPatches
	{
		[HarmonyBefore(new string[] { "com.nandbrew.nandtweaks" })]
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void InitializeSaveSlotsUI(StartMenu __instance, GameObject ___saveSlotUI)
		{
			SaveSlotsUI.InitializeUI(___saveSlotUI);
			Paginator.AddMoreSaveSlots(__instance.backupSavesUI, ___saveSlotUI.GetComponentsInChildren<StartMenuButton>(true));
		}

		[HarmonyPrefix]
		[HarmonyPatch("ButtonClick", new Type[] { typeof(StartMenuButtonType) })]
		public static bool ButtonClickPatch(StartMenuButtonType button)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Paginator.ButtonClick(button);
		}
	}

	[HarmonyPatch(typeof(BackupSavesListUI))]
	private class BackupSavesListUIPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("ShowList")]
		public static bool ShowList(StartMenuButton parentSlotButton, BackupSavesListUI __instance, ref int ___showingListFor)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (___showingListFor == parentSlotButton.saveSlot)
			{
				return false;
			}
			___showingListFor = parentSlotButton.saveSlot;
			bool active = false;
			((Component)__instance).transform.position = ((Component)parentSlotButton).transform.parent.position;
			if (parentSlotButton.saveSlot % 6 <= 2)
			{
				((Component)__instance).transform.Translate(Vector3.up * __instance.topRowOffset);
			}
			StartMenuButton[] buttons = __instance.buttons;
			StartMenuButton[] array = buttons;
			foreach (StartMenuButton val in array)
			{
				string backupPath = SaveSlots.GetBackupPath(parentSlotButton.saveSlot, val.saveSlot);
				if (File.Exists(backupPath))
				{
					active = true;
					DateTime lastWriteTime = File.GetLastWriteTime(backupPath);
					string buttonText = lastWriteTime.ToShortTimeString() + "\n" + lastWriteTime.ToShortDateString();
					val.SetButtonText(buttonText);
					((Component)((Component)val).transform.parent).gameObject.SetActive(true);
				}
				else
				{
					((Component)((Component)val).transform.parent).gameObject.SetActive(false);
				}
			}
			((Component)__instance.list).gameObject.SetActive(active);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		public static bool Update(BackupSavesListUI __instance, int ___showingListFor, Vector3 ___backButtonInitialPos, Vector3 ___backButtonAltPos)
		{
			//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_0052: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			if (!((Object)(object)__instance.currentLookedAtSlot == (Object)null))
			{
				__instance.ShowList(__instance.currentLookedAtSlot);
			}
			Vector3 val;
			if (___showingListFor % 6 == 4 && ((Component)__instance.list).gameObject.activeInHierarchy)
			{
				((Component)SaveSlotsUI.PageNumTextMesh).gameObject.SetActive(false);
				val = ___backButtonAltPos;
			}
			else
			{
				((Component)SaveSlotsUI.PageNumTextMesh).gameObject.SetActive(true);
				val = ___backButtonInitialPos;
			}
			__instance.backButton.parent.localPosition = Vector3.Lerp(__instance.backButton.parent.localPosition, val, Time.deltaTime * 8f);
			if (___showingListFor % 6 == 1 && ((Component)__instance.list).gameObject.activeInHierarchy)
			{
				__instance.chooseSlotText.SetActive(false);
			}
			else
			{
				__instance.chooseSlotText.SetActive(true);
			}
			return false;
		}
	}
}
internal class SaveSlotsUI
{
	internal const StartMenuButtonType PREVIOUS_BUTTON = 13;

	internal const StartMenuButtonType NEXT_BUTTON = 14;

	internal static TextMesh PageNumTextMesh { get; private set; }

	internal static void InitializeUI(GameObject saveSlotUI)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		saveSlotUI.transform.GetChild(12).localPosition = new Vector3(1.157f, 1.12f, 0.033f);
		Transform val = Object.Instantiate<Transform>(saveSlotUI.transform.GetChild(10));
		((Object)val).name = "previous button";
		val.SetParent(saveSlotUI.transform);
		val.localPosition = new Vector3(-1.45f, 0.5f, 0f);
		val.localEulerAngles = new Vector3(0f, 180f, 0f);
		val.localScale = new Vector3(1f, 1f, 1f);
		((Component)val.GetChild(1)).GetComponent<TextMesh>().text = "Previous";
		((Component)val.GetChild(2)).GetComponent<TextMesh>().text = "←";
		((Component)val.GetChild(0)).GetComponent<StartMenuButton>().SetPrivateField("type", (object)(StartMenuButtonType)13);
		Transform val2 = Object.Instantiate<Transform>(saveSlotUI.transform.GetChild(10));
		((Object)val2).name = "next button";
		val2.SetParent(saveSlotUI.transform);
		val2.localPosition = new Vector3(1.45f, 0.5f, 0f);
		val2.localEulerAngles = new Vector3(0f, 180f, 0f);
		val2.localScale = new Vector3(1f, 1f, 1f);
		((Component)val2.GetChild(1)).GetComponent<TextMesh>().text = "Next";
		((Component)val2.GetChild(2)).GetComponent<TextMesh>().text = "→";
		((Component)val2.GetChild(0)).GetComponent<StartMenuButton>().SetPrivateField("type", (object)(StartMenuButtonType)14);
		Transform val3 = Object.Instantiate<Transform>(saveSlotUI.transform.GetChild(3));
		((Object)val3).name = "page num text";
		val3.SetParent(saveSlotUI.transform);
		val3.localPosition = new Vector3(0f, 0.5f, 0f);
		val3.localEulerAngles = new Vector3(0f, 0f, 0f);
		val3.localScale = new Vector3(0.0165f, 0.0177f, 0.0177f);
		PageNumTextMesh = ((Component)val3).GetComponent<TextMesh>();
		PageNumTextMesh.text = "page 1";
	}

	internal static void UpdatePageNumText(int pageNum)
	{
		PageNumTextMesh.text = $"page {pageNum + 1}";
	}
}