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("SaveSlotsPlus")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("raddude")] [assembly: AssemblyProduct("SaveSlotsPlus")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(true)] [assembly: Guid("071994df-c696-4ece-ad36-48d4036214b5")] [assembly: AssemblyFileVersion("2.1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.0.0")] [module: UnverifiableCode] namespace SaveSlotsPlus; internal class Configs { internal static ConfigEntry numPages; internal static ConfigEntry altClickKey; 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)SSP_Plugin.Instance).Config; numPages = config.Bind("Settings", "Number of save slot pages
(must restart game)", 3, new ConfigDescription("The number of pages of save slots. Each page has 6 slots.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), Array.Empty())); altClickKey = config.Bind("Settings", "Alt Click Key", (KeyCode)324, "Key to click on a save slot to open the file menu."); } } internal static class Extensions { public static T GetPrivateField(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(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); } } internal class FileMenu { private static int _showingListFor = -1; private static int _copySlotNum = -1; private static bool _awaitingDeleteConfirm = false; internal static SaveNameInput SaveNameInputText { get; set; } internal static void SetShowingListFor(int slotNum) { _showingListFor = slotNum; } internal static void RenameButtonClicked() { SSP_Plugin.LogDebug($"Rename button clicked for slot {_showingListFor}"); if (SaveSlots.slotsActive[_showingListFor]) { SaveSlotsUI.ShowRenameInput(); SSP_Plugin.LogDebug($"Showing rename input for slot {_showingListFor}"); } } internal static void ConfirmRenameButtonClicked() { SSP_Plugin.LogDebug($"Confirm rename button clicked for slot {_showingListFor}"); SaveNameInputText.SaveName(_showingListFor); Paginator.RefreshSlot(_showingListFor); SaveSlotsUI.HideRenameInput(); SSP_Plugin.LogInfo($"Renamed slot {_showingListFor}"); } internal static void CopyButtonClicked() { SSP_Plugin.LogDebug($"Copy button clicked for slot {_showingListFor}"); if (SaveSlots.slotsActive[_showingListFor]) { _copySlotNum = _showingListFor; SaveSlotsUI.HideFileMenu(); SSP_Plugin.LogInfo($"Set slot {_copySlotNum} to be copied"); } } internal static void PasteButtonClicked() { SSP_Plugin.LogDebug($"Paste button clicked for slot {_showingListFor} with copy slot {_copySlotNum}"); if (File.Exists(SlotPath.SlotSavePath(_showingListFor)) || _copySlotNum <= -1) { return; } TryCopy(SlotPath.SlotSavePath(_copySlotNum), SlotPath.SlotSavePath(_showingListFor)); TryCopy(SlotPath.SlotScreenshotPath(_copySlotNum), SlotPath.SlotScreenshotPath(_showingListFor)); TryCopy(SlotPath.SlotMetaPath(_copySlotNum), SlotPath.SlotMetaPath(_showingListFor)); for (int i = 1; i <= 5; i++) { TryCopy(SlotPath.SlotBackupPath(_copySlotNum, i), SlotPath.SlotBackupPath(_showingListFor, i)); } string path = SlotPath.SlotModSavesDirPath(_copySlotNum); string text = SlotPath.SlotModSavesDirPath(_showingListFor); if (Directory.Exists(path)) { Directory.CreateDirectory(text); string[] files = Directory.GetFiles(path); foreach (string text2 in files) { string destFileName = Path.Combine(text, Path.GetFileName(text2)); File.Copy(text2, destFileName, overwrite: true); } } SaveSlots.slotsActive[_showingListFor] = true; SaveSlots.activeSlotsCount = Array.FindAll(SaveSlots.slotsActive, (bool s) => s).Length; Paginator.RefreshSlot(_showingListFor); SaveSlotsUI.CopyMaterial(_copySlotNum, _showingListFor); SaveSlotsUI.HideFileMenu(); SSP_Plugin.LogInfo($"Copied slot {_copySlotNum} to slot {_showingListFor}"); } internal static void DeleteButtonClicked() { SSP_Plugin.LogDebug($"Delete button clicked for slot {_showingListFor}"); if (SaveSlots.slotsActive[_showingListFor]) { if (!_awaitingDeleteConfirm) { _awaitingDeleteConfirm = true; } SaveSlotsUI.EnableConfirmDeleteButton(); SSP_Plugin.LogDebug($"Enabled confirm delete button for slot {_showingListFor}"); } } internal static void DeleteButtonConfirmClicked() { SSP_Plugin.LogDebug($"Confirm delete button clicked for slot {_showingListFor}"); if (_awaitingDeleteConfirm) { TryDelete(SlotPath.SlotSavePath(_showingListFor)); TryDelete(SlotPath.SlotScreenshotPath(_showingListFor)); TryDelete(SlotPath.SlotMetaPath(_showingListFor)); for (int i = 1; i <= 5; i++) { TryDelete(SlotPath.SlotBackupPath(_showingListFor, i)); } string path = SlotPath.SlotModSavesDirPath(_showingListFor); if (Directory.Exists(path)) { Directory.Delete(path, recursive: true); } SaveSlots.slotsActive[_showingListFor] = false; SaveSlots.activeSlotsCount = Array.FindAll(SaveSlots.slotsActive, (bool s) => s).Length; Paginator.RefreshSlot(_showingListFor); SaveSlotsUI.ResetMaterial(_showingListFor); SaveSlotsUI.HideFileMenu(); SSP_Plugin.LogInfo($"Deleted slot {_showingListFor}"); } } private static void TryCopy(string from, string to) { if (File.Exists(from)) { File.Copy(from, to, overwrite: true); } } private static void TryDelete(string path) { if (File.Exists(path)) { File.Delete(path); } } internal static void ClearAwaitingDeleteConfirm() { _awaitingDeleteConfirm = false; } internal static void ResetCopySlotNum() { _copySlotNum = -1; } } [BepInPlugin("com.raddude82.saveslotsplus", "SaveSlotsPlus", "2.1.0")] public class SSP_Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.raddude82.saveslotsplus"; public const string PLUGIN_NAME = "SaveSlotsPlus"; public const string PLUGIN_VERSION = "2.1.0"; private static ManualLogSource _logger; internal static SSP_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.raddude82.saveslotsplus"); } } internal class NewGamePatches { [HarmonyPatch(typeof(StartMenu))] private class StartMenuNewGamePatches { [HarmonyPostfix] [HarmonyPatch("Start")] public static void OnShowChooseIslandUI(GameObject ___chooseIslandUI) { NewGameUI.InitializeUI(___chooseIslandUI.transform); } [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) //IL_0003: Invalid comparison between Unknown and I4 if ((int)button == 0) { SaveGameInputText.Activate(); } return true; } [HarmonyPrefix] [HarmonyPatch("StartNewGame")] public static bool StartNewGame(GameObject ___chooseIslandUI) { SaveNameInput componentInChildren = ___chooseIslandUI.GetComponentInChildren(); componentInChildren.SaveName(SaveSlots.currentSlot); return true; } } internal static SaveNameInput SaveGameInputText { get; set; } } internal class NewGameUI { internal static void InitializeUI(Transform chooseIslandUI) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0097: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) Transform child = chooseIslandUI.GetChild(0); child.localPosition = new Vector3(0f, -0.449f, 0.07f); child.localScale = new Vector3(1.32f, 1.32f, 1.38f); chooseIslandUI.GetChild(2).localPosition = new Vector3(-0.005f, -0.361f, 0.037f); chooseIslandUI.GetChild(4).localPosition = new Vector3(-0.7f, -0.361f, 0.038f); chooseIslandUI.GetChild(6).localPosition = new Vector3(0.7f, -0.361f, 0.038f); chooseIslandUI.GetChild(5).localPosition = new Vector3(-0.005f, -0.716f, 0.037f); Transform child2 = chooseIslandUI.GetChild(3); child2.localPosition = new Vector3(-0.022f, -0.119f, 0.037f); Transform child3 = chooseIslandUI.GetChild(7); Transform val = Object.Instantiate(child2, child3); ((Object)val).name = "label"; ((Component)val).transform.localPosition = new Vector3(0f, 0f, 0.1f); ((Component)val).transform.localEulerAngles = new Vector3(0f, 270f, 270f); ((Component)val).transform.localScale = new Vector3(0.0194f, 0.0354f, 0.0194f); TextMesh component = ((Component)val).GetComponent(); component.text = "name your save:"; component.anchor = (TextAnchor)4; component.alignment = (TextAlignment)1; Transform val2 = Object.Instantiate(child2, child3); ((Object)val2).name = "input text"; ((Component)val2).transform.localPosition = new Vector3(0f, 0f, -0.1f); ((Component)val2).transform.localEulerAngles = new Vector3(0f, 270f, 270f); ((Component)val2).transform.localScale = new Vector3(0.0194f, 0.0354f, 0.0194f); TextMesh component2 = ((Component)val2).GetComponent(); component2.text = ""; component2.anchor = (TextAnchor)4; component2.alignment = (TextAlignment)1; component2.fontStyle = (FontStyle)0; NewGamePatches.SaveGameInputText = ((Component)child3).gameObject.AddComponent(); NewGamePatches.SaveGameInputText.displayMesh = component2; } } internal class Paginator { internal const int SLOTS_PER_PAGE = 6; private static int _currentPage = 0; private static readonly List _allSlotRoots = new List(); private static BackupSavesListUI _backUpSavesListUI; public static void AddMoreSaveSlots(BackupSavesListUI backupSavesListUI, StartMenuButton[] existingButtons) { _backUpSavesListUI = backupSavesListUI; List list = (from b in existingButtons where (int)b.GetPrivateField("type") == 8 orderby b.saveSlot select b).ToList(); foreach (StartMenuButton item in list) { _allSlotRoots.Add(((Component)((Component)item).transform.parent).gameObject); } for (int num = 6; num < 6 * Configs.numPages.Value; num++) { int index = num % 6; GameObject val = _allSlotRoots[index]; GameObject val2 = Object.Instantiate(val, val.transform.parent); ((Object)val2).name = $"SaveSlot_{num}"; StartMenuButton componentInChildren = val2.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.saveSlot = num; } val2.SetActive(false); _allSlotRoots.Add(val2); } } public static void RefreshSlotText(StartMenuButton btn) { if (SaveSlots.slotsActive != null && btn.saveSlot < SaveSlots.slotsActive.Length && SaveSlots.slotsActive[btn.saveSlot]) { string text = ((Component)((Component)btn).transform.parent.GetChild(1)).GetComponent().text; string text2 = SaveNameInput.LoadName(btn.saveSlot); string buttonText = ((text2 != null) ? (text2 + "\n" + text) : text); btn.SetButtonText(buttonText); } else { btn.SetButtonText("(empty)"); } } public static void PreviousButtonClicked() { SaveSlotsUI.HideFileMenu(); SaveSlotsUI.HideRenameInput(); _backUpSavesListUI.HideList(); _currentPage = Mathf.Max(0, _currentPage - 1); SaveSlotsUI.SetChangePageTextColor((StartMenuButtonType)13, isActive: true, changeBoth: true); if (_currentPage == 0) { SaveSlotsUI.SetChangePageTextColor((StartMenuButtonType)13, isActive: false); } SaveSlotsUI.UpdatePageNumText(_currentPage); ShowPage(_currentPage); SSP_Plugin.LogDebug($"Previous button clicked, showing page {_currentPage + 1}"); } public static void NextButtonClicked() { SaveSlotsUI.HideFileMenu(); SaveSlotsUI.HideRenameInput(); _backUpSavesListUI.HideList(); _currentPage = Mathf.Min(Configs.numPages.Value - 1, _currentPage + 1); SaveSlotsUI.SetChangePageTextColor((StartMenuButtonType)14, isActive: true, changeBoth: true); if (_currentPage == Configs.numPages.Value - 1) { SaveSlotsUI.SetChangePageTextColor((StartMenuButtonType)14, isActive: false); } SaveSlotsUI.UpdatePageNumText(_currentPage); ShowPage(_currentPage); SSP_Plugin.LogDebug($"Next button clicked, showing page {_currentPage + 1}"); } 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 static void RefreshSlot(int slot) { StartMenuButton startMenuButtonForSlot = GetStartMenuButtonForSlot(slot); if ((Object)(object)startMenuButtonForSlot != (Object)null) { DateTime lastWriteTime = File.GetLastWriteTime(SaveSlots.GetSlotSavePath(slot)); string buttonText = $"{lastWriteTime:t}\n{lastWriteTime:d}"; startMenuButtonForSlot.SetButtonText(buttonText); } RefreshSlotText(startMenuButtonForSlot); } internal static StartMenuButton GetStartMenuButtonForSlot(int slot) { if (slot < _allSlotRoots.Count) { return _allSlotRoots[slot].GetComponentInChildren(); } return null; } } 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++; } } SSP_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, __instance.backupSavesUI); Paginator.AddMoreSaveSlots(__instance.backupSavesUI, ___saveSlotUI.GetComponentsInChildren(true)); } [HarmonyPostfix] [HarmonyPatch("EnableSlotMenu")] public static void GetLabelText(GameObject ___saveSlotUI) { if ((Object)(object)_nandTweaksLabelText == (Object)null) { _nandTweaksLabelText = ((Component)___saveSlotUI.transform.Find("label text")).GetComponent(); } } [HarmonyPrefix] [HarmonyPatch("ButtonClick", new Type[] { typeof(StartMenuButtonType) })] public static bool ButtonClickPatch(StartMenuButtonType button, GameObject ___saveSlotUI) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Invalid comparison between Unknown and I4 //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Invalid comparison between Unknown and I4 //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Invalid comparison between Unknown and I4 if ((int)button == 13) { Paginator.PreviousButtonClicked(); } else if ((int)button == 14) { Paginator.NextButtonClicked(); } else if ((int)button == 15) { FileMenu.RenameButtonClicked(); } else if ((int)button == 17) { FileMenu.CopyButtonClicked(); SaveSlotsUI.CopyButtonClicked(); } else if ((int)button == 18) { FileMenu.PasteButtonClicked(); } else if ((int)button == 19) { FileMenu.DeleteButtonClicked(); } else if ((int)button == 20) { FileMenu.DeleteButtonConfirmClicked(); } else { if ((int)button != 16) { if ((int)button == 3) { FileMenu.ClearAwaitingDeleteConfirm(); FileMenu.ResetCopySlotNum(); SaveSlotsUI.ClearCopyClicked(); SaveSlotsUI.HideFileMenu(); SaveSlotsUI.HideRenameInput(); return true; } return true; } FileMenu.ConfirmRenameButtonClicked(); } return false; } } [HarmonyPatch(typeof(StartMenuButton))] private class StartMenuButtonPatches { [HarmonyPostfix] [HarmonyPatch("Awake")] public static void AwakePatch(StartMenuButton __instance, StartMenuButtonType ___type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)___type == 8) { Paginator.RefreshSlotText(__instance); } } [HarmonyPostfix] [HarmonyPatch("ExtraLateUpdate")] public static void ExtraLateUpdatePatch(StartMenuButton __instance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((int)__instance.GetPrivateField("type") == 8 && __instance.GetPrivateField("isLookedAt") && Input.GetKeyDown(Configs.altClickKey.Value)) { SaveSlotsUI.ToggleFileMenu(__instance); } } } [HarmonyPatch(typeof(BackupSavesListUI))] private class BackupSavesListUIPatches { [HarmonyPrefix] [HarmonyPatch("ShowList")] public static bool ShowList(StartMenuButton parentSlotButton, BackupSavesListUI __instance, ref int ___showingListFor) { //IL_0050: 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_0081: Unknown result type (might be due to invalid IL or missing references) if (___showingListFor == parentSlotButton.saveSlot) { return false; } SaveSlotsUI.HideFileMenu(); SaveSlotsUI.HideRenameInput(); FileMenu.ClearAwaitingDeleteConfirm(); FileMenu.SetShowingListFor(parentSlotButton.saveSlot); ___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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0067: 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_00a7: 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.FileMenuList).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 || ((Component)SaveSlotsUI.FileMenuList).gameObject.activeInHierarchy)) { __instance.chooseSlotText.SetActive(false); if ((Object)(object)_nandTweaksLabelText != (Object)null && _nandTweaksLabelText.text != "") { _nandTweaksLabelText.text = ""; } } else { __instance.chooseSlotText.SetActive(true); if ((Object)(object)_nandTweaksLabelText != (Object)null && _nandTweaksLabelText.text != "Continue") { _nandTweaksLabelText.text = "Continue"; } } return false; } } private static TextMesh _nandTweaksLabelText; } internal class SaveNameInput : MonoBehaviour { private const int MAX_LENGTH = 13; private const float CURSOR_BLINK_RATE = 0.5f; internal TextMesh displayMesh; private string _currentText = ""; private int _cursorPos = 0; private float _cursorTimer = 0f; private bool _showCursor = true; private bool _isActive = false; private void Update() { if (!_isActive) { return; } if (Input.GetKeyDown((KeyCode)276)) { _cursorPos = Mathf.Max(0, _cursorPos - 1); ResetCursorBlink(); } else if (Input.GetKeyDown((KeyCode)275)) { _cursorPos = Mathf.Min(_currentText.Length, _cursorPos + 1); ResetCursorBlink(); } string inputString = Input.inputString; for (int i = 0; i < inputString.Length; i++) { char c = inputString[i]; if (c == '\b') { if (_cursorPos > 0) { _currentText = _currentText.Remove(_cursorPos - 1, 1); _cursorPos--; ResetCursorBlink(); } } else if (_currentText.Length < 13) { _currentText = _currentText.Insert(_cursorPos, c.ToString()); _cursorPos++; ResetCursorBlink(); } } _cursorTimer += Time.deltaTime; if (_cursorTimer >= 0.5f) { _showCursor = !_showCursor; _cursorTimer = 0f; } UpdateDisplay(); } private void UpdateDisplay() { if (!((Object)(object)displayMesh == (Object)null) && _isActive) { string text = _currentText.Substring(0, _cursorPos); string text2 = _currentText.Substring(_cursorPos); displayMesh.text = text + (_showCursor ? "|" : " ") + text2; } } private void ResetCursorBlink() { _showCursor = true; _cursorTimer = 0f; UpdateDisplay(); } internal void Activate() { _currentText = ""; _isActive = true; _showCursor = true; _cursorTimer = 0f; _cursorPos = 0; if ((Object)(object)displayMesh != (Object)null) { displayMesh.text = _currentText; } } internal void Deactivate() { _isActive = false; _showCursor = false; } internal void SaveName(int slot) { string text = _currentText.Trim(); if (!string.IsNullOrWhiteSpace(text)) { File.WriteAllText(SlotPath.SlotMetaPath(slot), text.Trim()); SSP_Plugin.LogInfo($"Saved name '{text}' for slot {slot}"); } } internal static string LoadName(int slot) { string path = SlotPath.SlotMetaPath(slot); if (File.Exists(path)) { return File.ReadAllText(path).Trim(); } return null; } } internal class SaveSlotsUI { internal const StartMenuButtonType PREVIOUS_BUTTON = (StartMenuButtonType)13; internal const StartMenuButtonType NEXT_BUTTON = (StartMenuButtonType)14; internal const StartMenuButtonType RENAME_BUTTON = (StartMenuButtonType)15; internal const StartMenuButtonType CONFIRM_RENAME_BUTTON = (StartMenuButtonType)16; internal const StartMenuButtonType COPY_BUTTON = (StartMenuButtonType)17; internal const StartMenuButtonType PASTE_BUTTON = (StartMenuButtonType)18; internal const StartMenuButtonType DELETE_BUTTON = (StartMenuButtonType)19; internal const StartMenuButtonType CONFIRM_DELETE_BUTTON = (StartMenuButtonType)20; private static Transform _renameScroll; private static Transform _confirmRenameButton; private static Transform _previousButton; private static Transform _nextButton; private static bool _fileMenuShowing = false; private static Transform _list = null; private static bool _listWasInactive = false; private static bool _copyClicked = false; private static readonly Color32 ACTIVE_COLOR = new Color32((byte)17, (byte)17, (byte)19, byte.MaxValue); private static readonly Color32 INACTIVE_COLOR = new Color32((byte)17, (byte)17, (byte)19, (byte)102); private static Material _originalSlotButtonMaterial; private const int ORIGINAL_FONT_SIZE = 50; private static readonly Vector3 ORIGINAL_FONT_POSITION = new Vector3(0f, 0.0225f, 0.004f); internal static TextMesh PageNumTextMesh { get; private set; } internal static Transform FileMenuList { get; private set; } internal static void InitializeUI(GameObject saveSlotUI, BackupSavesListUI backupSavesUI) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0566: Unknown result type (might be due to invalid IL or missing references) _originalSlotButtonMaterial = ((Renderer)((Component)saveSlotUI.transform.GetChild(2).GetChild(0)).GetComponent()).material; saveSlotUI.transform.GetChild(12).localPosition = new Vector3(1.157f, 1.12f, 0.033f); _previousButton = Object.Instantiate(saveSlotUI.transform.GetChild(10), saveSlotUI.transform); ((Object)_previousButton).name = "previous button"; _previousButton.localPosition = new Vector3(-1.45f, 0.5f, 0f); _previousButton.localEulerAngles = new Vector3(0f, 180f, 0f); _previousButton.localScale = new Vector3(1f, 1f, 1f); ((Component)_previousButton.GetChild(1)).GetComponent().text = "previous"; ((Component)_previousButton.GetChild(2)).GetComponent().text = "←"; ((Component)_previousButton.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)13); SetChangePageTextColor((StartMenuButtonType)13, isActive: false); _nextButton = Object.Instantiate(saveSlotUI.transform.GetChild(10), saveSlotUI.transform); ((Object)_nextButton).name = "next button"; _nextButton.localPosition = new Vector3(1.45f, 0.5f, 0f); _nextButton.localEulerAngles = new Vector3(0f, 180f, 0f); _nextButton.localScale = new Vector3(1f, 1f, 1f); ((Component)_nextButton.GetChild(1)).GetComponent().text = "next"; ((Component)_nextButton.GetChild(2)).GetComponent().text = "→"; ((Component)_nextButton.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)14); _confirmRenameButton = Object.Instantiate(saveSlotUI.transform.GetChild(10), saveSlotUI.transform); ((Object)_confirmRenameButton).name = "confirm rename button"; _confirmRenameButton.localPosition = new Vector3(0f, -0.2f, 0f); _confirmRenameButton.localEulerAngles = new Vector3(0f, 180f, 0f); _confirmRenameButton.localScale = new Vector3(0.9f, 0.9f, 0.9f); Transform child = _confirmRenameButton.GetChild(2); child.localScale = new Vector3(0.0135f, 0.0135f, 0.0135f); child.localPosition = new Vector3(0.0028f, 0.025f, 0.0009f); TextMesh component = ((Component)child).GetComponent(); component.text = "confirm\nrename"; component.fontSize = 60; ((Component)_confirmRenameButton.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)16); Object.Destroy((Object)(object)((Component)_confirmRenameButton.GetChild(1)).gameObject); ((Component)_confirmRenameButton).gameObject.SetActive(false); Transform child2 = saveSlotUI.transform.GetChild(3); Transform val = Object.Instantiate(child2, saveSlotUI.transform); ((Object)val).name = "page num text"; val.localPosition = new Vector3(0f, 0.5f, 0f); val.localEulerAngles = new Vector3(0f, 0f, 0f); val.localScale = new Vector3(0.0165f, 0.0177f, 0.0177f); PageNumTextMesh = ((Component)val).GetComponent(); PageNumTextMesh.text = "page 1"; _renameScroll = Object.Instantiate(saveSlotUI.transform.GetChild(0), saveSlotUI.transform); ((Object)_renameScroll).name = "bg rename"; ((Component)_renameScroll).transform.localScale = new Vector3(0.6f, 4f, 0.42f); ((Component)_renameScroll).transform.localPosition = new Vector3(0.15f, 0.087f, 0.06f); Transform val2 = Object.Instantiate(child2, _renameScroll); ((Object)val2).name = "label"; ((Component)val2).transform.localPosition = new Vector3(-0.17f, 0.04f, 0.1f); ((Component)val2).transform.localEulerAngles = new Vector3(0f, 180f, 270f); ((Component)val2).transform.localScale = new Vector3(0.004f, 0.035f, 0.0194f); TextMesh component2 = ((Component)val2).GetComponent(); component2.text = "name your save:"; component2.anchor = (TextAnchor)4; component2.alignment = (TextAlignment)1; Transform val3 = Object.Instantiate(child2, _renameScroll); ((Object)val3).name = "input text"; ((Component)val3).transform.localPosition = new Vector3(0.05f, 0.04f, 0.1f); ((Component)val3).transform.localEulerAngles = new Vector3(0f, 180f, 270f); ((Component)val3).transform.localScale = new Vector3(0.005f, 0.035f, 0.0194f); TextMesh component3 = ((Component)val3).GetComponent(); component3.text = ""; component3.anchor = (TextAnchor)4; component3.alignment = (TextAlignment)1; component3.fontStyle = (FontStyle)0; FileMenu.SaveNameInputText = ((Component)_renameScroll).gameObject.AddComponent(); FileMenu.SaveNameInputText.displayMesh = component3; ((Component)_renameScroll).gameObject.SetActive(false); FileMenuList = Object.Instantiate(backupSavesUI.list, backupSavesUI.list.parent); ((Object)FileMenuList).name = "file menu list"; ((Component)FileMenuList.GetChild(6)).GetComponent().text = "file menu"; Transform child3 = FileMenuList.GetChild(0); ((Object)child3).name = "rename button"; ((Component)child3.GetChild(1)).GetComponent().text = "rename"; ((Component)child3.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)15); Transform child4 = FileMenuList.GetChild(1); ((Object)child4).name = "copy button"; ((Component)child4.GetChild(1)).GetComponent().text = "copy"; ((Component)child4.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)17); Transform child5 = FileMenuList.GetChild(2); ((Object)child5).name = "paste button"; ((Component)child5.GetChild(1)).GetComponent().text = "paste"; ((Component)child5.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)18); Transform child6 = FileMenuList.GetChild(3); ((Object)child6).name = "delete button"; ((Component)child6.GetChild(1)).GetComponent().text = "delete"; ((Component)child6.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)19); Transform child7 = FileMenuList.GetChild(4); ((Object)child7).name = "confirm delete button"; ((Component)child7.GetChild(1)).GetComponent().text = "confirm\ndelete"; ((Component)child7.GetChild(0)).GetComponent().SetPrivateField("type", (object)(StartMenuButtonType)20); } internal static void ShowRenameInput() { ((Component)_renameScroll).gameObject.SetActive(true); FileMenu.SaveNameInputText.Activate(); ((Component)_confirmRenameButton).gameObject.SetActive(true); HideFileMenu(); } internal static void HideRenameInput() { ((Component)_renameScroll).gameObject.SetActive(false); FileMenu.SaveNameInputText.Deactivate(); ((Component)_confirmRenameButton).gameObject.SetActive(false); } internal static void HideFileMenu() { _fileMenuShowing = false; _listWasInactive = false; ((Component)FileMenuList).gameObject.SetActive(false); } internal static void ToggleFileMenu(StartMenuButton startMenuButton) { SSP_Plugin.LogDebug("Toggling file menu"); if ((Object)(object)_list == (Object)null) { _list = ((Component)startMenuButton.GetPrivateField("menu").backupSavesUI).transform.GetChild(0); } if (!_fileMenuShowing) { _fileMenuShowing = true; ((Component)FileMenuList).gameObject.SetActive(true); if (SaveSlots.slotsActive[startMenuButton.saveSlot]) { SetActiveSaveSlotTextColors(); } else { SetNotActiveSaveSlotColors(); } if (!((Component)_list).gameObject.activeInHierarchy) { _listWasInactive = true; } else { ((Component)_list).gameObject.SetActive(false); } } else { _fileMenuShowing = false; ((Component)FileMenuList).gameObject.SetActive(false); if (_listWasInactive) { ((Component)_list).gameObject.SetActive(false); _listWasInactive = false; } else { ((Component)_list).gameObject.SetActive(true); } } } private static void SetActiveSaveSlotTextColors() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) ((Component)FileMenuList.GetChild(0).GetChild(1)).GetComponent().color = Color32.op_Implicit(ACTIVE_COLOR); ((Component)FileMenuList.GetChild(1).GetChild(1)).GetComponent().color = Color32.op_Implicit(ACTIVE_COLOR); ((Component)FileMenuList.GetChild(2).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); ((Component)FileMenuList.GetChild(3).GetChild(1)).GetComponent().color = Color32.op_Implicit(ACTIVE_COLOR); ((Component)FileMenuList.GetChild(4).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); } private static void SetNotActiveSaveSlotColors() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //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_0071: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) ((Component)FileMenuList.GetChild(0).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); ((Component)FileMenuList.GetChild(1).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); ((Component)FileMenuList.GetChild(2).GetChild(1)).GetComponent().color = Color32.op_Implicit(_copyClicked ? ACTIVE_COLOR : INACTIVE_COLOR); ((Component)FileMenuList.GetChild(3).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); ((Component)FileMenuList.GetChild(4).GetChild(1)).GetComponent().color = Color32.op_Implicit(INACTIVE_COLOR); } internal static void SetChangePageTextColor(StartMenuButtonType type, bool isActive, bool changeBoth = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_001d: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0043: 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_00b4: Unknown result type (might be due to invalid IL or missing references) Transform val = (((int)type == 13) ? _previousButton : _nextButton); Color32 val2 = (isActive ? ACTIVE_COLOR : INACTIVE_COLOR); if (!changeBoth) { TextMesh[] componentsInChildren = ((Component)val).GetComponentsInChildren(); foreach (TextMesh val3 in componentsInChildren) { val3.color = Color32.op_Implicit(val2); } return; } TextMesh[] componentsInChildren2 = ((Component)_previousButton).GetComponentsInChildren(); foreach (TextMesh val4 in componentsInChildren2) { val4.color = Color32.op_Implicit(val2); } TextMesh[] componentsInChildren3 = ((Component)_nextButton).GetComponentsInChildren(); foreach (TextMesh val5 in componentsInChildren3) { val5.color = Color32.op_Implicit(val2); } } internal static void EnableConfirmDeleteButton() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) ((Component)FileMenuList.GetChild(4).GetChild(1)).GetComponent().color = Color32.op_Implicit(ACTIVE_COLOR); } internal static void UpdatePageNumText(int pageNum) { PageNumTextMesh.text = $"page {pageNum + 1}"; } internal static void CopyButtonClicked() { _copyClicked = true; } internal static void ClearCopyClicked() { _copyClicked = false; } internal static void CopyMaterial(int fromSlot, int toSlot) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) string path = SlotPath.SlotScreenshotPath(fromSlot); StartMenuButton startMenuButtonForSlot = Paginator.GetStartMenuButtonForSlot(fromSlot); StartMenuButton startMenuButtonForSlot2 = Paginator.GetStartMenuButtonForSlot(toSlot); MeshRenderer component = ((Component)startMenuButtonForSlot2).GetComponent(); TextMesh componentInChildren = ((Component)((Component)startMenuButtonForSlot2).transform.parent).GetComponentInChildren(); if (File.Exists(path)) { ((Renderer)component).material = ((Renderer)((Component)startMenuButtonForSlot).GetComponent()).material; componentInChildren.color = new Color(1f, 0.8f, 0.6f); componentInChildren.fontSize = 45; ((Component)componentInChildren).transform.localPosition = new Vector3(0f, -0.1f, 0.04f); } else { ((Renderer)((Component)startMenuButtonForSlot2).GetComponent()).material = _originalSlotButtonMaterial; componentInChildren.color = Color32.op_Implicit(ACTIVE_COLOR); componentInChildren.fontSize = 50; ((Component)componentInChildren).transform.localPosition = ORIGINAL_FONT_POSITION; } } internal static void ResetMaterial(int slot) { //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_004a: Unknown result type (might be due to invalid IL or missing references) StartMenuButton startMenuButtonForSlot = Paginator.GetStartMenuButtonForSlot(slot); ((Renderer)((Component)startMenuButtonForSlot).GetComponent()).material = _originalSlotButtonMaterial; TextMesh componentInChildren = ((Component)((Component)startMenuButtonForSlot).transform.parent).GetComponentInChildren(); componentInChildren.color = Color32.op_Implicit(ACTIVE_COLOR); componentInChildren.fontSize = 50; ((Component)componentInChildren).transform.localPosition = ORIGINAL_FONT_POSITION; } } internal class SlotPath { internal static string SlotSavePath(int slot) { return $"{Application.persistentDataPath}/slot{slot}.save"; } internal static string SlotBackupPath(int slot, int backupNum) { return $"{Application.persistentDataPath}/slot{slot}_backup{backupNum}.save"; } internal static string SlotMetaPath(int slot) { return $"{Application.persistentDataPath}/slot{slot}.save.meta"; } internal static string SlotScreenshotPath(int slot) { return $"{Application.persistentDataPath}/slot{slot}.save.png"; } internal static string SlotModSavesDirPath(int slot) { return $"{Application.persistentDataPath}/slot{slot}"; } }