diff --git a/S1API/Internal/Patches/GenericSaveables.Patches.cs b/S1API/Internal/Patches/GenericSaveables.Patches.cs index f7b98ed..c972bd8 100644 --- a/S1API/Internal/Patches/GenericSaveables.Patches.cs +++ b/S1API/Internal/Patches/GenericSaveables.Patches.cs @@ -71,13 +71,14 @@ 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. /// 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. + /// 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] @@ -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) {