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.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("NoSaveDeleteMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("NoSaveDeleteMod")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("194122da-d5ca-4c8a-b922-4931bcfb19f6")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] public class AutoLoadMultiplayer { private static async void Postfix() { if (!SemiFunc.IsMultiplayer()) { return; } if (!MyModConfig.AutoLoadInMultiplayer.Value) { Debug.Log((object)"[NoSaveDelete] Auto-load disabled due to AutoLoadInMultiplayer being enabled."); } else { if (!PhotonNetwork.IsMasterClient) { return; } FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); List list = SemiFunc.PlayerGetList(); bool flag = true; foreach (PlayerAvatar item in list) { if (!(bool)fieldInfo.GetValue(item)) { Debug.Log((object)"[NoSaveDelete] Not all players are dead. Reload is not performed."); flag = false; break; } } if (flag) { PreventSaveGameUltimate.SetAllPlayersDead(); FieldInfo fieldInfo2 = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); string saveFileName = (string)fieldInfo2.GetValue(StatsManager.instance); if (string.IsNullOrEmpty(saveFileName)) { Debug.LogWarning((object)"[NoSaveDelete] No save file to load!"); PreventSaveGameUltimate.ResetAllPlayersDead(); } else if (RunManager.instance.levelShop.Contains(RunManager.instance.levelCurrent)) { Debug.Log((object)"[NoSaveDelete] All players died in the SHOP. Restarting save WITHOUT restoring backup..."); await Task.Delay(650); SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); PreventSaveGameUltimate.ResetAllPlayersDead(); } else { Debug.Log((object)"[NoSaveDelete] All players died. Restoring backup..."); RestoreBackup(saveFileName); await Task.Delay(650); SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); await Task.Delay(1500); ReloadSaveInMemory(saveFileName); PreventSaveGameUltimate.ResetAllPlayersDead(); } } } } private static void ReloadSaveInMemory(string saveFileName) { try { MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { saveFileName, null }); Debug.Log((object)("[NoSaveDelete] Save data reloaded in memory for " + saveFileName)); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for memory reload!"); } } catch (Exception ex) { Debug.LogError((object)("[NoSaveDelete] Error reloading save in memory: " + ex.Message)); } } private static void RestoreBackup(string saveFileName) { string text = Path.Combine(Application.persistentDataPath, "saves", saveFileName); if (!Directory.Exists(text)) { Debug.LogError((object)("[NoSaveDelete] Save folder not found: " + text)); return; } string text2 = FindLatestBackup(text, saveFileName); if (!string.IsNullOrEmpty(text2)) { try { string text3 = Path.Combine(text, saveFileName + ".es3"); if (File.Exists(text3)) { File.Delete(text3); } File.Copy(text2, text3); Debug.Log((object)("[NoSaveDelete] Backup restored from: " + text2)); MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { saveFileName, null }); Debug.Log((object)("[NoSaveDelete] Save data reloaded in memory for " + saveFileName)); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for memory reload!"); } return; } catch (IOException ex) { Debug.LogError((object)("[NoSaveDelete] Restore error: " + ex.Message)); return; } } Debug.LogWarning((object)"[NoSaveDelete] No valid backup found!"); } private static string FindLatestBackup(string directory, string saveFileName) { if (!Directory.Exists(directory)) { return null; } string[] files = Directory.GetFiles(directory, saveFileName + "_BACKUP*.es3"); if (files.Length == 0) { return null; } Regex regex = new Regex("_BACKUP(\\d+)", RegexOptions.IgnoreCase); return (from file in files select new { FilePath = file, BackupNumber = ExtractBackupNumber(file, regex) } into b where b.BackupNumber >= 0 orderby b.BackupNumber descending select b).FirstOrDefault()?.FilePath; } private static int ExtractBackupNumber(string filePath, Regex regex) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); Match match = regex.Match(fileNameWithoutExtension); if (match.Success && int.TryParse(match.Groups[1].Value, out var result)) { return result; } return -1; } } [HarmonyPatch(typeof(GameDirector), "Update")] public class CheckArenaAndRestoreBackup { private static bool shouldRestoreBackup; private static bool hasLoggedArena; private static void Postfix(GameDirector __instance) { if (!MyModConfig.AutoLoadInMultiplayer.Value && SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { bool num = RunManager.instance.levelArena.Contains(RunManager.instance.levelCurrent); bool flag = (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobbyMenu; if (num && !hasLoggedArena) { hasLoggedArena = true; shouldRestoreBackup = true; Debug.Log((object)"[NoSaveDelete] The game is on the arena. Enabling backup restoration after returning to the lobby."); } if (shouldRestoreBackup && flag) { shouldRestoreBackup = false; hasLoggedArena = false; DelayedRestoreBackup(); } } } private static async Task DelayedRestoreBackup() { Debug.Log((object)"[NoSaveDelete] Waiting 3 seconds before restoring the backup..."); await Task.Delay(3000); RestoreBackup(); } private static void RestoreBackup() { string text = (string)AccessTools.Field(typeof(StatsManager), "saveFileCurrent").GetValue(StatsManager.instance); if (string.IsNullOrEmpty(text)) { Debug.LogWarning((object)"[NoSaveDelete] No active save file!"); return; } string text2 = Path.Combine(Application.persistentDataPath, "saves", text); if (!Directory.Exists(text2)) { Debug.LogError((object)("[NoSaveDelete] Save folder not found: " + text2)); return; } string text3 = FindLatestBackup(text2, text); if (!string.IsNullOrEmpty(text3)) { try { string text4 = Path.Combine(text2, text + ".es3"); if (File.Exists(text4)) { File.Delete(text4); } File.Copy(text3, text4); Debug.Log((object)("[NoSaveDelete] Backup successfully restored from: " + text3)); MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { text, null }); Debug.Log((object)("[NoSaveDelete] Called LoadGame() for " + text + ", data updated in memory.")); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for reflection call!"); } return; } catch (IOException ex) { Debug.LogError((object)("[NoSaveDelete] Restore error: " + ex.Message)); return; } } Debug.LogWarning((object)"[NoSaveDelete] No backup found! Using the standard save."); } private static string FindLatestBackup(string directory, string saveFileName) { if (!Directory.Exists(directory)) { Debug.LogError((object)"[NoSaveDelete] Save directory is empty or does not exist!"); return null; } string[] files = Directory.GetFiles(directory, saveFileName + "_BACKUP*.es3"); if (files.Length == 0) { Debug.LogWarning((object)"[NoSaveDelete] No backup files found."); return null; } Regex regex = new Regex("_BACKUP(\\d+)", RegexOptions.IgnoreCase); var anon = (from file in files select new { FilePath = file, BackupNumber = ExtractBackupNumber(file, regex) } into b where b.BackupNumber >= 0 orderby b.BackupNumber descending select b).FirstOrDefault(); if (anon == null) { Debug.LogWarning((object)"[NoSaveDelete] Unable to determine the latest backup."); return null; } Debug.Log((object)$"[NoSaveDelete] Selected backup: {anon.FilePath} (number {anon.BackupNumber})"); return anon.FilePath; } private static int ExtractBackupNumber(string filePath, Regex regex) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); Match match = regex.Match(fileNameWithoutExtension); if (match.Success && int.TryParse(match.Groups[1].Value, out var result)) { return result; } return -1; } public static void ResetFlags() { shouldRestoreBackup = false; hasLoggedArena = false; Debug.Log((object)"[NoSaveDelete] Backup flags have been reset."); } } [HarmonyPatch(typeof(RunManager), "LeaveToMainMenu")] public class ResetBackupFlagsOnMainMenuLeave { private static void Prefix() { object value = AccessTools.Field(typeof(CheckArenaAndRestoreBackup), "shouldRestoreBackup").GetValue(null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { CheckArenaAndRestoreBackup.ResetFlags(); Debug.Log((object)"[NoSaveDelete] The host has left the arena and returned to the main menu. Resetting flags..."); } else { Debug.Log((object)"[NoSaveDelete] Returning to the main menu. Flags were not set — no reset needed."); } } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeath")] public class AutoLoadSingleplayer { [HarmonyPatch(typeof(PlayerAvatar), "Revive")] public class CancelAutoLoadOnRevive { private static void Prefix() { if (_cancellationTokenSource != null) { _cancellationTokenSource.Cancel(); Debug.Log((object)"[NoSaveDelete] Player revived. Auto-load canceled."); } PreventSaveGameUltimate.ResetPlayerDied(); } } private static CancellationTokenSource _cancellationTokenSource; private static async void Prefix() { if (MyModConfig.AllowGameDelete.Value) { Debug.Log((object)"[NoSaveDelete] Auto-load disabled due to AllowGameDelete being enabled."); } else { if (SemiFunc.IsMultiplayer()) { return; } if (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsArena()) { Debug.Log((object)"[NoSaveDelete] Player died in lobby/shop. Auto-load disabled."); return; } PreventSaveGameUltimate.SetPlayerDied(); FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); string saveFileName = (string)fieldInfo.GetValue(StatsManager.instance); if (!string.IsNullOrEmpty(saveFileName)) { Debug.Log((object)("[NoSaveDelete] The player has died. Reloading the last save: " + saveFileName)); _cancellationTokenSource?.Cancel(); _cancellationTokenSource = new CancellationTokenSource(); CancellationToken token = _cancellationTokenSource.Token; try { await Task.Delay(4000, token); if (!token.IsCancellationRequested) { SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); await Task.Delay(1000, token); if (!token.IsCancellationRequested) { ReloadSaveInMemory(saveFileName); } PreventSaveGameUltimate.ResetPlayerDied(); } return; } catch (TaskCanceledException) { Debug.Log((object)"[NoSaveDelete] Auto-load was canceled because the player revived."); PreventSaveGameUltimate.ResetPlayerDied(); return; } } Debug.LogWarning((object)"[NoSaveDelete] No save file to load!"); PreventSaveGameUltimate.ResetPlayerDied(); } } private static void ReloadSaveInMemory(string saveFileName) { try { MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { saveFileName, null }); Debug.Log((object)("[NoSaveDelete] Save Data for " + saveFileName + ", updated in memory.")); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for memory reload!"); } } catch (Exception ex) { Debug.LogError((object)("[NoSaveDelete] Error reloading save in memory: " + ex.Message)); } } } public static class MyModConfig { public static ConfigEntry AllowPlayerDelete; public static ConfigEntry AllowGameDelete; public static ConfigEntry AutoLoadInMultiplayer; public static void Init(ConfigFile config) { AllowPlayerDelete = config.Bind("Settings", "AllowPlayerDelete", true, "Allow the player to delete saves? (true - yes, false - no)"); AllowGameDelete = config.Bind("Settings", "AllowGameDelete", false, "Allow the game to delete saves? (true - yes, false - no)"); AutoLoadInMultiplayer = config.Bind("Settings", "AutoLoadInMultiplayer", false, "Enable automatically load the last save in Multiplayer if ALL players die? (true - yes, false - no)"); } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] public class InGameSaveSelectorInjector { private static void Postfix(PlayerAvatar __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); Debug.Log((object)"[NoSaveDelete] InGameSaveSelector added to player!"); } } } public class InGameSaveSelector : MonoBehaviour { private class SaveFileInfo { public string fileName; public string teamName; public string dateTime; public int level; public int currency; public int totalHaul; public float timePlayed; public List playerNames; public bool isValid; public List backups; } private bool showUI; private Rect windowRect = new Rect((float)(Screen.width / 2 - 400), (float)(Screen.height / 2 - 350), 800f, 700f); private Vector2 scrollPosition = Vector2.zero; private GUIStyle windowStyle; private GUIStyle labelStyle; private GUIStyle buttonStyle; private GUIStyle currentSaveStyle; private GUIStyle saveButtonStyle; private GUIStyle deleteButtonStyle; private GUIStyle renameButtonStyle; private GUIStyle scrollViewStyle; private bool stylesInitialized; private List saveFiles = new List(); private bool savesLoaded; private string currentSaveFileName = ""; private bool showLoadConfirmation; private string selectedSaveToLoad = ""; private bool showDeleteConfirmation; private string selectedSaveToDelete = ""; private bool showNewSaveDialog; private string newSaveName = ""; private bool showRenameDialog; private string selectedSaveToRename = ""; private string renameSaveNewName = ""; private void Awake() { Debug.Log((object)"[NoSaveDelete] InGameSaveSelector Awake() called"); } private void Update() { if (Input.GetKeyDown((KeyCode)288)) { showUI = !showUI; if (showUI) { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; if (!savesLoaded) { LoadSaveFiles(); } } else if (!SemiFunc.IsMainMenu() && !SemiFunc.RunIsLobbyMenu()) { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } Debug.Log((object)$"[NoSaveDelete] Save selector UI toggled: {showUI}"); } if (!showUI || !Input.GetKeyDown((KeyCode)27)) { return; } if (showLoadConfirmation) { showLoadConfirmation = false; return; } if (showDeleteConfirmation) { showDeleteConfirmation = false; return; } if (showNewSaveDialog) { showNewSaveDialog = false; return; } if (showRenameDialog) { showRenameDialog = false; return; } showUI = false; if (!SemiFunc.IsMainMenu() && !SemiFunc.RunIsLobbyMenu()) { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } } private void OnGUI() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (showUI) { InitializeStyles(); if (showLoadConfirmation) { DrawLoadConfirmationWindow(); } else if (showDeleteConfirmation) { DrawDeleteConfirmationWindow(); } else if (showNewSaveDialog) { DrawNewSaveDialog(); } else if (showRenameDialog) { DrawRenameDialog(); } else { windowRect = GUI.Window(54321, windowRect, new WindowFunction(DrawMainWindow), "Save File Manager (No_Save_Delete)", windowStyle); } } } private void InitializeStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0079: 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_00a4: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown if (!stylesInitialized) { windowStyle = new GUIStyle(GUI.skin.window); windowStyle.fontSize = 13; windowStyle.fontStyle = (FontStyle)1; windowStyle.normal.textColor = Color.white; labelStyle = new GUIStyle(GUI.skin.label); labelStyle.fontSize = 13; labelStyle.normal.textColor = Color.white; labelStyle.wordWrap = true; buttonStyle = new GUIStyle(GUI.skin.button); buttonStyle.fontSize = 14; buttonStyle.fontStyle = (FontStyle)1; buttonStyle.padding = new RectOffset(10, 10, 8, 8); currentSaveStyle = new GUIStyle(GUI.skin.box); currentSaveStyle.fontSize = 13; currentSaveStyle.normal.textColor = Color.green; currentSaveStyle.normal.background = MakeTexture(2, 2, new Color(0f, 0.3f, 0f, 0.5f)); currentSaveStyle.padding = new RectOffset(10, 10, 10, 10); saveButtonStyle = new GUIStyle(GUI.skin.button); saveButtonStyle.fontSize = 12; saveButtonStyle.padding = new RectOffset(6, 6, 5, 5); saveButtonStyle.margin = new RectOffset(2, 2, 2, 2); deleteButtonStyle = new GUIStyle(GUI.skin.button); deleteButtonStyle.fontSize = 12; deleteButtonStyle.normal.textColor = Color.red; deleteButtonStyle.padding = new RectOffset(6, 6, 5, 5); deleteButtonStyle.margin = new RectOffset(2, 2, 2, 2); renameButtonStyle = new GUIStyle(GUI.skin.button); renameButtonStyle.fontSize = 12; renameButtonStyle.padding = new RectOffset(6, 6, 5, 5); renameButtonStyle.margin = new RectOffset(2, 2, 2, 2); scrollViewStyle = new GUIStyle(GUI.skin.scrollView); stylesInitialized = true; Debug.Log((object)"[NoSaveDelete] Save selector styles initialized"); } } private void DrawMainWindow(int windowID) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(10f); FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); currentSaveFileName = (string)fieldInfo.GetValue(StatsManager.instance); if (!string.IsNullOrEmpty(currentSaveFileName)) { GUILayout.BeginVertical(currentSaveStyle, Array.Empty()); GUILayout.Label("✅ Current Save: " + currentSaveFileName, labelStyle, Array.Empty()); GUILayout.EndVertical(); GUILayout.Space(5f); } GUILayout.Label($"\ud83c\udfae Available Save Files: ({saveFiles.Count})", labelStyle, Array.Empty()); GUILayout.Space(5f); if (!savesLoaded) { GUILayout.Label("⏳ Loading saves...", labelStyle, Array.Empty()); } else if (saveFiles.Count == 0) { GUILayout.Label("❌ No save files found!", labelStyle, Array.Empty()); } else { scrollPosition = GUILayout.BeginScrollView(scrollPosition, scrollViewStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(450f) }); foreach (SaveFileInfo saveFile in saveFiles) { DrawSaveFileEntry(saveFile); GUILayout.Space(3f); } GUILayout.EndScrollView(); } GUILayout.Space(10f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("➕ New Save", buttonStyle, Array.Empty())) { newSaveName = ""; showNewSaveDialog = true; } if (GUILayout.Button("\ud83d\udd04 Refresh", buttonStyle, Array.Empty())) { savesLoaded = false; LoadSaveFiles(); } if (GUILayout.Button("❌ Close [F7 / ESC]", buttonStyle, Array.Empty())) { showUI = false; if (!SemiFunc.IsMainMenu() && !SemiFunc.RunIsLobbyMenu()) { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } } GUILayout.EndHorizontal(); GUI.DragWindow(); } private void DrawSaveFileEntry(SaveFileInfo save) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0082: 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_009b: Expected O, but got Unknown //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Expected O, but got Unknown bool flag = save.fileName == currentSaveFileName; Color backgroundColor = GUI.backgroundColor; if (flag) { GUI.backgroundColor = new Color(0.2f, 0.8f, 0.2f, 1f); } GUILayout.BeginVertical(GUI.skin.box, Array.Empty()); GUI.backgroundColor = backgroundColor; GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label((flag ? "\ud83d\udfe2 " : "⚪ ") + save.teamName, new GUIStyle(labelStyle) { fontSize = 15, fontStyle = (FontStyle)1 }, Array.Empty()); GUILayout.FlexibleSpace(); if (!flag && save.isValid) { if (GUILayout.Button("\ud83d\udcc2 Load", saveButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { selectedSaveToLoad = save.fileName; showLoadConfirmation = true; } } else if (flag) { GUILayout.Label("✅ Active", saveButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); } if (save.isValid && GUILayout.Button("Rename", renameButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { selectedSaveToRename = save.fileName; renameSaveNewName = save.teamName; showRenameDialog = true; } if (GUILayout.Button("\ud83d\uddd1\ufe0f Delete", deleteButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { selectedSaveToDelete = save.fileName; showDeleteConfirmation = true; } GUILayout.EndHorizontal(); if (save.isValid) { GUILayout.Label("\ud83d\udcc5 " + save.dateTime, labelStyle, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label($"\ud83d\ude9a Level: {save.level + 1}", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label($"\ud83d\udcb0 Money: {save.currency}k", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }); GUILayout.Label("⏱\ufe0f Time: " + FormatTime(save.timePlayed), labelStyle, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Label($"\ud83d\udcb5 Total Haul: ${save.totalHaul}k", labelStyle, Array.Empty()); if (save.playerNames != null && save.playerNames.Count > 0) { GUILayout.Label("\ud83d\udc65 Players: " + string.Join(", ", save.playerNames), labelStyle, Array.Empty()); } if (save.backups != null && save.backups.Count > 0) { GUILayout.Label($"\ud83d\udcbe Backups: {save.backups.Count}", labelStyle, Array.Empty()); } } else { GUIStyle val = new GUIStyle(labelStyle); val.normal.textColor = Color.red; GUILayout.Label("⚠\ufe0f CORRUPTED SAVE FILE", val, Array.Empty()); } GUILayout.EndVertical(); } private void DrawLoadConfirmationWindow() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor((float)(Screen.width / 2 - 200), (float)(Screen.height / 2 - 100), 400f, 200f); GUI.Window(54322, val, new WindowFunction(DrawLoadConfirmation), "⚠\ufe0f Load Save?", windowStyle); } private void DrawLoadConfirmation(int windowID) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0033: Expected O, but got Unknown //IL_0053: 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_0060: 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_0078: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown GUILayout.Space(15f); GUILayout.Label("Are you sure you want to load this save?", new GUIStyle(labelStyle) { fontSize = 14, alignment = (TextAnchor)4 }, Array.Empty()); GUILayout.Space(5f); GUILayout.Label("Save: " + selectedSaveToLoad, new GUIStyle(labelStyle) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }, Array.Empty()); GUILayout.Space(10f); GUIStyle val = new GUIStyle(labelStyle); val.normal.textColor = Color.yellow; val.alignment = (TextAnchor)4; GUILayout.Label("⚠\ufe0f Current progress will be lost!", val, Array.Empty()); GUILayout.Space(20f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("✅ Yes, Load Save", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { LoadSelectedSave(); showLoadConfirmation = false; } if (GUILayout.Button("❌ Cancel", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { showLoadConfirmation = false; } GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.Label("Press ESC to cancel", labelStyle, Array.Empty()); } private void DrawDeleteConfirmationWindow() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor((float)(Screen.width / 2 - 200), (float)(Screen.height / 2 - 100), 400f, 200f); GUI.Window(54323, val, new WindowFunction(DrawDeleteConfirmation), "⚠\ufe0f Delete Save?", windowStyle); } private void DrawDeleteConfirmation(int windowID) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0033: Expected O, but got Unknown //IL_0053: 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_0060: 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_0078: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown GUILayout.Space(15f); GUILayout.Label("Are you sure you want to DELETE this save?", new GUIStyle(labelStyle) { fontSize = 14, alignment = (TextAnchor)4 }, Array.Empty()); GUILayout.Space(5f); GUILayout.Label("Save: " + selectedSaveToDelete, new GUIStyle(labelStyle) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }, Array.Empty()); GUILayout.Space(10f); GUIStyle val = new GUIStyle(labelStyle); val.normal.textColor = Color.red; val.alignment = (TextAnchor)4; GUILayout.Label("⚠\ufe0f This action CANNOT be undone!", val, Array.Empty()); GUILayout.Space(20f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("\ud83d\uddd1\ufe0f Yes, Delete Forever", deleteButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { DeleteSelectedSave(); showDeleteConfirmation = false; } if (GUILayout.Button("❌ Cancel", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { showDeleteConfirmation = false; } GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.Label("Press ESC to cancel", labelStyle, Array.Empty()); } private void DrawNewSaveDialog() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor((float)(Screen.width / 2 - 250), (float)(Screen.height / 2 - 100), 500f, 200f); GUI.Window(54324, val, new WindowFunction(DrawNewSave), "➕ Create New Save", windowStyle); } private void DrawNewSave(int windowID) { GUILayout.Space(15f); GUILayout.Label("Enter team name for new save:", labelStyle, Array.Empty()); GUILayout.Space(5f); GUI.SetNextControlName("NewSaveNameField"); newSaveName = GUILayout.TextField(newSaveName, 30, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.Space(20f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("✅ Create Save", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { CreateNewSave(); } if (GUILayout.Button("❌ Cancel", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { showNewSaveDialog = false; } GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.Label("Press ESC to cancel", labelStyle, Array.Empty()); GUI.FocusControl("NewSaveNameField"); } private void DrawRenameDialog() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor((float)(Screen.width / 2 - 250), (float)(Screen.height / 2 - 100), 500f, 200f); GUI.Window(54325, val, new WindowFunction(DrawRename), "✏\ufe0f Rename Save", windowStyle); } private void DrawRename(int windowID) { GUILayout.Space(15f); GUILayout.Label("Renaming: " + selectedSaveToRename, labelStyle, Array.Empty()); GUILayout.Space(5f); GUILayout.Label("New team name:", labelStyle, Array.Empty()); GUILayout.Space(5f); GUI.SetNextControlName("RenameField"); renameSaveNewName = GUILayout.TextField(renameSaveNewName, 30, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUILayout.Space(20f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("✅ Rename", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { RenameSelectedSave(); } if (GUILayout.Button("❌ Cancel", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { showRenameDialog = false; } GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.Label("Press ESC to cancel", labelStyle, Array.Empty()); GUI.FocusControl("RenameField"); } private async Task LoadSaveFiles() { savesLoaded = false; saveFiles.Clear(); Debug.Log((object)"[NoSaveDelete] Loading save files..."); Task> task = StatsManager.instance.SaveFileGetAllAsync(); await task; foreach (SaveFolder item in task.Result) { SaveFileInfo saveFileInfo = new SaveFileInfo(); saveFileInfo.fileName = item.name; saveFileInfo.backups = item.backups; string text = StatsManager.instance.SaveFileGetTeamName(item.name, (string)null); string text2 = StatsManager.instance.SaveFileGetDateAndTime(item.name, (string)null); if (int.TryParse(StatsManager.instance.SaveFileGetRunLevel(item.name, (string)null), out var result) && int.TryParse(StatsManager.instance.SaveFileGetRunCurrency(item.name, (string)null), out var result2) && int.TryParse(StatsManager.instance.SaveFileGetTotalHaul(item.name, (string)null), out var result3)) { saveFileInfo.isValid = true; saveFileInfo.teamName = text ?? item.name; saveFileInfo.dateTime = text2 ?? "Unknown date"; saveFileInfo.level = result; saveFileInfo.currency = result2; saveFileInfo.totalHaul = result3; saveFileInfo.timePlayed = StatsManager.instance.SaveFileGetTimePlayed(item.name, (string)null); saveFileInfo.playerNames = StatsManager.instance.SaveFileGetPlayerNames(item.name, (string)null); } else { saveFileInfo.isValid = false; saveFileInfo.teamName = item.name + " (CORRUPTED)"; saveFileInfo.dateTime = "N/A"; } saveFiles.Add(saveFileInfo); } savesLoaded = true; Debug.Log((object)$"[NoSaveDelete] Loaded {saveFiles.Count} save files"); } private async void LoadSelectedSave() { if (string.IsNullOrEmpty(selectedSaveToLoad)) { Debug.LogWarning((object)"[NoSaveDelete] No save selected to load!"); return; } Debug.Log((object)("[NoSaveDelete] Loading save: " + selectedSaveToLoad)); if (SemiFunc.IsMultiplayer()) { PreventSaveGameUltimate.SetAllPlayersDead(); } else { PreventSaveGameUltimate.SetPlayerDied(); } SaveFileInfo saveInfo = saveFiles.FirstOrDefault((SaveFileInfo s) => s.fileName == selectedSaveToLoad); if (saveInfo != null) { SemiFunc.MenuActionSingleplayerGame(saveInfo.fileName, saveInfo.backups); await Task.Delay(1500); ReloadSaveInMemory(saveInfo.fileName); } if (SemiFunc.IsMultiplayer()) { PreventSaveGameUltimate.ResetAllPlayersDead(); } else { PreventSaveGameUltimate.ResetPlayerDied(); } showUI = false; if (!SemiFunc.IsMainMenu() && !SemiFunc.RunIsLobbyMenu()) { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } } private void ReloadSaveInMemory(string saveFileName) { try { MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { saveFileName, null }); Debug.Log((object)("[NoSaveDelete] Save data reloaded in memory for " + saveFileName)); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for memory reload!"); } } catch (Exception ex) { Debug.LogError((object)("[NoSaveDelete] Error reloading save in memory: " + ex.Message)); } } private void DeleteSelectedSave() { if (string.IsNullOrEmpty(selectedSaveToDelete)) { Debug.LogWarning((object)"[NoSaveDelete] No save selected to delete!"); return; } Debug.Log((object)("[NoSaveDelete] Deleting save from UI: " + selectedSaveToDelete)); MenuPageSavesPatch.IsPlayerDeletingSave = true; StatsManager.instance.SaveFileDelete(selectedSaveToDelete); MenuPageSavesPatch.IsPlayerDeletingSave = false; savesLoaded = false; LoadSaveFiles(); Debug.Log((object)"[NoSaveDelete] Save deleted successfully!"); } private void CreateNewSave() { if (string.IsNullOrWhiteSpace(newSaveName)) { newSaveName = "R.E.P.O."; } Debug.Log((object)("[NoSaveDelete] Creating new save with name: " + newSaveName)); AccessTools.Field(typeof(StatsManager), "teamName").SetValue(StatsManager.instance, newSaveName); StatsManager.instance.SaveFileCreate("", false); showNewSaveDialog = false; savesLoaded = false; LoadSaveFiles(); Debug.Log((object)"[NoSaveDelete] New save created successfully!"); } private void RenameSelectedSave() { if (string.IsNullOrEmpty(selectedSaveToRename) || string.IsNullOrWhiteSpace(renameSaveNewName)) { Debug.LogWarning((object)"[NoSaveDelete] Invalid rename parameters!"); return; } Debug.Log((object)("[NoSaveDelete] Renaming save " + selectedSaveToRename + " to " + renameSaveNewName)); MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { selectedSaveToRename, null }); } AccessTools.Field(typeof(StatsManager), "teamName").SetValue(StatsManager.instance, renameSaveNewName); MethodInfo method2 = typeof(StatsManager).GetMethod("SaveGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 != null) { method2.Invoke(StatsManager.instance, new object[1] { selectedSaveToRename }); } showRenameDialog = false; savesLoaded = false; LoadSaveFiles(); Debug.Log((object)"[NoSaveDelete] Save renamed successfully!"); } private string FormatTime(float timeInSeconds) { int num = (int)(timeInSeconds / 3600f); int num2 = (int)(timeInSeconds % 3600f / 60f); if (num > 0) { return $"{num}h {num2}m"; } return $"{num2}m"; } private Texture2D MakeTexture(int width, int height, Color color) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = color; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } } [HarmonyPatch(typeof(MenuPageSaves), "OnDeleteGame")] public class MenuPageSavesPatch { public static bool IsPlayerDeletingSave; private static bool Prefix() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) Debug.Log((object)$"Attempt to delete the save. AllowPlayerDelete = {MyModConfig.AllowPlayerDelete.Value}"); if (!MyModConfig.AllowPlayerDelete.Value) { Debug.Log((object)"The player is not allowed to delete the save (config prohibits it)."); MenuManager.instance.PagePopUp("Delete blocked.", Color.red, "You cannot delete the save. Please change the mod config.", "OK", false); return false; } Debug.Log((object)"The player is deleting the save."); IsPlayerDeletingSave = true; return true; } } [BepInPlugin("com.PxntxrezStudio.nosavedelete", "NoSaveDelete", "1.3.0")] public class MyMod : BaseUnityPlugin { private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) MyModConfig.Init(((BaseUnityPlugin)this).Config); new Harmony("com.PxntxrezStudio.nosavedelete").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Mod NoSaveDelete loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Settings can be changed in BepInEx/config/com.PxntxrezStudio.nosavedelete.cfg"); } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] public class QuickReloadInjector { private static void Postfix(PlayerAvatar __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); Debug.Log((object)"[NoSaveDelete] QuickSaveReload added to player!"); } } } public class QuickSaveReload : MonoBehaviour { private bool isReloading; private void Update() { if (Input.GetKeyDown((KeyCode)290) && !isReloading) { Debug.Log((object)"[NoSaveDelete] F9 pressed - Quick reload initiated!"); QuickReloadSave(); } } private async Task QuickReloadSave() { if (isReloading) { Debug.Log((object)"[NoSaveDelete] Reload already in progress!"); return; } isReloading = true; FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); string saveFileName = (string)fieldInfo.GetValue(StatsManager.instance); if (string.IsNullOrEmpty(saveFileName)) { Debug.LogWarning((object)"[NoSaveDelete] No active save file to reload!"); isReloading = false; return; } Debug.Log((object)("[NoSaveDelete] Quick reloading save: " + saveFileName)); if (SemiFunc.IsMultiplayer()) { if (!PhotonNetwork.IsMasterClient) { Debug.Log((object)"[NoSaveDelete] Only master client can reload in multiplayer!"); isReloading = false; return; } PreventSaveGameUltimate.SetAllPlayersDead(); if (RunManager.instance.levelShop.Contains(RunManager.instance.levelCurrent)) { Debug.Log((object)"[NoSaveDelete] Quick reload in SHOP. Restarting without backup restore..."); await Task.Delay(650); SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); PreventSaveGameUltimate.ResetAllPlayersDead(); isReloading = false; return; } Debug.Log((object)"[NoSaveDelete] Restoring backup for multiplayer quick reload..."); RestoreBackup(saveFileName); await Task.Delay(650); SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); await Task.Delay(1500); ReloadSaveInMemory(saveFileName); PreventSaveGameUltimate.ResetAllPlayersDead(); isReloading = false; } else { PreventSaveGameUltimate.SetPlayerDied(); Debug.Log((object)"[NoSaveDelete] Quick reloading in singleplayer..."); await Task.Delay(650); SemiFunc.MenuActionSingleplayerGame(saveFileName, (List)null); await Task.Delay(1000); ReloadSaveInMemory(saveFileName); PreventSaveGameUltimate.ResetPlayerDied(); isReloading = false; } Debug.Log((object)"[NoSaveDelete] Quick reload completed!"); } private void RestoreBackup(string saveFileName) { string text = Path.Combine(Application.persistentDataPath, "saves", saveFileName); if (!Directory.Exists(text)) { Debug.LogError((object)("[NoSaveDelete] Save folder not found: " + text)); return; } string text2 = FindLatestBackup(text, saveFileName); if (!string.IsNullOrEmpty(text2)) { try { string text3 = Path.Combine(text, saveFileName + ".es3"); if (File.Exists(text3)) { File.Delete(text3); } File.Copy(text2, text3); Debug.Log((object)("[NoSaveDelete] Backup restored from: " + text2)); return; } catch (IOException ex) { Debug.LogError((object)("[NoSaveDelete] Restore error: " + ex.Message)); return; } } Debug.LogWarning((object)"[NoSaveDelete] No valid backup found!"); } private string FindLatestBackup(string directory, string saveFileName) { if (!Directory.Exists(directory)) { return null; } string[] files = Directory.GetFiles(directory, saveFileName + "_BACKUP*.es3"); if (files.Length == 0) { return null; } Regex regex = new Regex("_BACKUP(\\d+)", RegexOptions.IgnoreCase); return (from file in files select new { FilePath = file, BackupNumber = ExtractBackupNumber(file, regex) } into b where b.BackupNumber >= 0 orderby b.BackupNumber descending select b).FirstOrDefault()?.FilePath; } private int ExtractBackupNumber(string filePath, Regex regex) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); Match match = regex.Match(fileNameWithoutExtension); if (match.Success && int.TryParse(match.Groups[1].Value, out var result)) { return result; } return -1; } private void ReloadSaveInMemory(string saveFileName) { try { MethodInfo method = typeof(StatsManager).GetMethod("LoadGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(StatsManager.instance, new object[2] { saveFileName, null }); Debug.Log((object)("[NoSaveDelete] Save data reloaded in memory for " + saveFileName)); } else { Debug.LogWarning((object)"[NoSaveDelete] Unable to find LoadGame method for memory reload!"); } } catch (Exception ex) { Debug.LogError((object)("[NoSaveDelete] Error reloading save in memory: " + ex.Message)); } } } [HarmonyPatch(typeof(MenuPageSaves), "OnNewGame")] public class RemoveSaveLimitInMenuPatch { private static bool Prefix(MenuPageSaves __instance) { if (SemiFunc.MainMenuIsMultiplayer()) { SemiFunc.MenuActionHostGame((string)null, (List)null); } else { SemiFunc.MenuActionSingleplayerGame((string)null, (List)null); } Debug.Log((object)"[NoSaveDelete] Creating new save (limit bypass active)"); return false; } } [HarmonyPatch(typeof(MenuPageSaves), "Start")] public class SaveLimitRemovalLogger { private static void Postfix() { Debug.Log((object)"[NoSaveDelete] ========================================"); Debug.Log((object)"[NoSaveDelete] Save limit (10 max) has been REMOVED!"); Debug.Log((object)"[NoSaveDelete] You can now create UNLIMITED saves!"); Debug.Log((object)"[NoSaveDelete] ========================================"); } } [HarmonyPatch(typeof(StatsManager), "SaveFileDelete")] public class SaveFileDeletePatch { private static bool Prefix(string saveFileName) { if (MenuPageSavesPatch.IsPlayerDeletingSave) { Debug.Log((object)("Player delete save " + saveFileName + ".")); MenuPageSavesPatch.IsPlayerDeletingSave = false; return true; } if (MyModConfig.AllowGameDelete.Value) { Debug.Log((object)("Game delete save " + saveFileName + " (allowed by config).")); return true; } Debug.Log((object)("The game tried to delete the save " + saveFileName + ", but the mod blocked it.")); return false; } } [HarmonyPatch(typeof(StatsManager), "SaveGame")] public class PreventSaveGameUltimate { private static bool playerJustDied; private static bool allPlayersDeadInMultiplayer; private static bool Prefix(ref string fileName) { if (MyModConfig.AllowGameDelete.Value) { return true; } if (RunManager.instance.levelArena.Contains(RunManager.instance.levelCurrent)) { Debug.Log((object)"[NoSaveDelete] Blocking loss of items, charges, HP, and more has been activated! Because AllowGameDelete = false!"); return false; } if (allPlayersDeadInMultiplayer && SemiFunc.IsMultiplayer()) { Debug.Log((object)"[NoSaveDelete] Blocking save because all players are dead in multiplayer!"); return false; } if (playerJustDied && !SemiFunc.IsMultiplayer()) { Debug.Log((object)"[NoSaveDelete] Blocking save because player just died in singleplayer!"); return false; } return true; } public static void SetPlayerDied() { playerJustDied = true; Debug.Log((object)"[NoSaveDelete] Player death flag set - saves will be blocked"); } public static void ResetPlayerDied() { playerJustDied = false; Debug.Log((object)"[NoSaveDelete] Player death flag reset - saves allowed"); } public static void SetAllPlayersDead() { allPlayersDeadInMultiplayer = true; Debug.Log((object)"[NoSaveDelete] All players dead flag set - multiplayer saves will be blocked"); } public static void ResetAllPlayersDead() { allPlayersDeadInMultiplayer = false; Debug.Log((object)"[NoSaveDelete] All players dead flag reset - multiplayer saves allowed"); } }