From c3571c876e5504062e43e710af72b8218b681aa2 Mon Sep 17 00:00:00 2001
From: k0 <21180271+k073l@users.noreply.github.com>
Date: Mon, 1 Jun 2026 16:16:25 +0200
Subject: [PATCH 1/3] fix(saveables): switch to onLoadComplete flag lock
---
.../Patches/GenericSaveables.Patches.cs | 29 ++++++++++++++-----
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/S1API/Internal/Patches/GenericSaveables.Patches.cs b/S1API/Internal/Patches/GenericSaveables.Patches.cs
index f7b98ed..7853dcb 100644
--- a/S1API/Internal/Patches/GenericSaveables.Patches.cs
+++ b/S1API/Internal/Patches/GenericSaveables.Patches.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using HarmonyLib;
+using MelonLoader;
using Newtonsoft.Json;
using S1API.Internal.Abstraction;
using S1API.Saveables;
@@ -71,7 +72,7 @@ private static void SaveManager_Save_Postfix(string saveFolderPath)
}
}
- private static string lastLoadedGameFolderPath = null;
+ private static bool sameSession = false;
///
/// Loads saveables marked with BeforeBaseGame load order BEFORE base game loaders run.
@@ -89,12 +90,9 @@ private static void BeforeBaseLoaders(S1Persistence.LoadRequest request)
if (lm == null || string.IsNullOrEmpty(lm.LoadedGameFolderPath))
return;
- // Only run once per load cycle by checking if the folder path has changed
- if (lastLoadedGameFolderPath == lm.LoadedGameFolderPath)
- return;
-
- lastLoadedGameFolderPath = lm.LoadedGameFolderPath;
-
+ // QueueLoadRequest may be called multiple times before loading into a save
+ // this flag makes sure we only load once - it's cleared by onLoadComplete
+ if (sameSession) return;
string basePath = Path.Combine(lm.LoadedGameFolderPath, "Modded", "Saveables");
foreach (var saveable in SaveableAutoRegistry.GetRegisteredSaveables())
@@ -129,6 +127,23 @@ void InitializeOnLoadComplete()
EventHelper.AddListener(InitializeOnLoadComplete, lm.onLoadComplete);
}
}
+
+ // Lock subsequent calls to this prefix until load completes to avoid loading multiple times in the same session
+ sameSession = true;
+ // Clear the lock once the game is loaded to allow loading again in future sessions without restarting the game
+ void ClearLockOnLoadComplete()
+ {
+ try
+ {
+ EventHelper.RemoveListener(ClearLockOnLoadComplete, lm.onLoadComplete);
+ sameSession = false;
+ }
+ catch (Exception e)
+ {
+ try { MelonLoader.MelonLogger.Warning($"[Saveables] ClearLockOnLoadComplete failed: {e.Message}\n{e.StackTrace}"); } catch { }
+ }
+ }
+ EventHelper.AddListener(ClearLockOnLoadComplete, lm.onLoadComplete);
}
catch (Exception e)
{
From 85172408410b4149d287ed5ca513bd30c9277eee Mon Sep 17 00:00:00 2001
From: k0 <21180271+k073l@users.noreply.github.com>
Date: Mon, 1 Jun 2026 16:46:20 +0200
Subject: [PATCH 2/3] fix(saveables): update docstring, remove ML import
---
S1API/Internal/Patches/GenericSaveables.Patches.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/S1API/Internal/Patches/GenericSaveables.Patches.cs b/S1API/Internal/Patches/GenericSaveables.Patches.cs
index 7853dcb..cdd4454 100644
--- a/S1API/Internal/Patches/GenericSaveables.Patches.cs
+++ b/S1API/Internal/Patches/GenericSaveables.Patches.cs
@@ -1,7 +1,6 @@
using System;
using System.IO;
using HarmonyLib;
-using MelonLoader;
using Newtonsoft.Json;
using S1API.Internal.Abstraction;
using S1API.Saveables;
@@ -78,7 +77,7 @@ private static void SaveManager_Save_Postfix(string saveFolderPath)
/// Loads saveables marked with BeforeBaseGame load order BEFORE base game loaders run.
/// This runs as a prefix to LoadManager.QueueLoadRequest on the first LoadRequest creation,
/// which happens right before base game loaders start processing.
- /// Uses the LoadedGameFolderPath to detect new load cycles.
+ /// Uses a session flag cleared by onLoadComplete to detect new load cycles.
///
[HarmonyPatch(typeof(S1Persistence.LoadManager), nameof(S1Persistence.LoadManager.QueueLoadRequest))]
[HarmonyPrefix]
From 90a163b9ba6fec6617bad0880af344ddeb6f4fa0 Mon Sep 17 00:00:00 2001
From: ifBars
Date: Wed, 3 Jun 2026 16:57:59 -0700
Subject: [PATCH 3/3] docs(saveables): clarify before-base load cycle detection
---
S1API/Internal/Patches/GenericSaveables.Patches.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/S1API/Internal/Patches/GenericSaveables.Patches.cs b/S1API/Internal/Patches/GenericSaveables.Patches.cs
index cdd4454..c972bd8 100644
--- a/S1API/Internal/Patches/GenericSaveables.Patches.cs
+++ b/S1API/Internal/Patches/GenericSaveables.Patches.cs
@@ -76,8 +76,9 @@ private static void SaveManager_Save_Postfix(string saveFolderPath)
///
/// Loads saveables marked with BeforeBaseGame load order BEFORE base game loaders run.
/// This runs as a prefix to LoadManager.QueueLoadRequest on the first LoadRequest creation,
- /// which happens right before base game loaders start processing.
- /// Uses a session flag cleared by onLoadComplete to detect new load cycles.
+ /// before base game loaders start processing.
+ /// Uses an internal sameSession flag to detect new load cycles. sameSession is reset by
+ /// onLoadComplete so subsequent load cycles can be detected.
///
[HarmonyPatch(typeof(S1Persistence.LoadManager), nameof(S1Persistence.LoadManager.QueueLoadRequest))]
[HarmonyPrefix]