From 70c04adfe5db537a3a0f47cc40a382899b632107 Mon Sep 17 00:00:00 2001 From: Lee23 <31892011+LeeTwentyThree@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:49:36 -0500 Subject: [PATCH] fix: FINALLY fix prefab request & caching issues (#525) * Remove requests array and lock cache dictionary Freddy 5 bear or or or or or * Change duplicate cache entries log level to debug * Removed unnecessary lock statement The game is single threaded, so the lock does nothing. * Attempt to make Nautilus construct prefabs once * Make sure to clear the running prefabs on quit * Add back warning log --------- Co-authored-by: Metious <71298690+Metious@users.noreply.github.com> --- Nautilus/Assets/ModPrefabCache.cs | 34 +++++++++++----------- Nautilus/Assets/ModPrefabRequest.cs | 1 - Nautilus/Handlers/PrefabHandler.cs | 16 ++++++++++ Nautilus/Patchers/PrefabDatabasePatcher.cs | 5 ---- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Nautilus/Assets/ModPrefabCache.cs b/Nautilus/Assets/ModPrefabCache.cs index 78412c3b..73b52670 100644 --- a/Nautilus/Assets/ModPrefabCache.cs +++ b/Nautilus/Assets/ModPrefabCache.cs @@ -11,8 +11,9 @@ namespace Nautilus.Assets; /// public static class ModPrefabCache { + internal static HashSet RunningPrefabs = new(); + private static ModPrefabCacheInstance _cacheInstance; - internal static Dictionary Requests { get; } = new Dictionary(); /// Adds the given prefab to the cache. /// The prefab object that is disabled and cached. @@ -84,39 +85,38 @@ private void Awake() gameObject.AddComponent(); DontDestroyOnLoad(gameObject); + SaveUtils.RegisterOnQuitEvent(ModPrefabCache.RunningPrefabs.Clear); } public void EnterPrefabIntoCache(GameObject prefab) { - // Proper prefabs can never exist in the scene, so parenting them is dangerous and pointless. - if(prefab.IsPrefab()) - { - InternalLogger.Debug($"Game Object: {prefab} is a proper prefab. Skipping parenting for cache."); - } - else - { - prefab.transform.parent = _prefabRoot; - prefab.SetActive(true); - } - var prefabIdentifier = prefab.GetComponent(); - if(prefabIdentifier == null) + if (prefabIdentifier == null) { InternalLogger.Warn($"ModPrefabCache: prefab {prefab.name} is missing a PrefabIdentifier component! Unable to add to cache."); return; } - // Proper prefabs can never exist in the scene, so parenting them is dangerous and pointless. - if(!Entries.ContainsKey(prefabIdentifier.classId)) + if (!Entries.ContainsKey(prefabIdentifier.classId)) { Entries.Add(prefabIdentifier.classId, prefab); InternalLogger.Debug($"ModPrefabCache: added prefab {prefab}"); + // Proper prefabs can never exist in the scene, so parenting them is dangerous and pointless. + if (prefab.IsPrefab()) + { + InternalLogger.Debug($"Game Object: {prefab} is a proper prefab. Skipping parenting for cache."); + } + else + { + prefab.transform.parent = _prefabRoot; + prefab.SetActive(true); + } } - else // this should never happen + else // This should never happen { InternalLogger.Warn($"ModPrefabCache: prefab {prefabIdentifier.classId} already existed in cache!"); - } + } } public void RemoveCachedPrefab(string classId) diff --git a/Nautilus/Assets/ModPrefabRequest.cs b/Nautilus/Assets/ModPrefabRequest.cs index 56495031..35e7d308 100644 --- a/Nautilus/Assets/ModPrefabRequest.cs +++ b/Nautilus/Assets/ModPrefabRequest.cs @@ -20,7 +20,6 @@ internal class ModPrefabRequest: IPrefabRequest public ModPrefabRequest(PrefabInfo prefabInfo) { this.prefabInfo = prefabInfo; - ModPrefabCache.Requests[prefabInfo.ClassID] = this; } private void Init() diff --git a/Nautilus/Handlers/PrefabHandler.cs b/Nautilus/Handlers/PrefabHandler.cs index 3cda6a83..95708b8a 100644 --- a/Nautilus/Handlers/PrefabHandler.cs +++ b/Nautilus/Handlers/PrefabHandler.cs @@ -20,6 +20,11 @@ public static class PrefabHandler internal static IEnumerator GetPrefabAsync(TaskResult gameObject, PrefabInfo info, PrefabFactoryAsync prefabFactory) { + if (ModPrefabCache.RunningPrefabs.Contains(info.ClassID)) + { + yield return new WaitUntil(() => ModPrefabCache.RunningPrefabs.Contains(info.ClassID) is false); + } + if (ModPrefabCache.TryGetPrefabFromCache(info.ClassID, out var prefabInCache)) { gameObject.Set(prefabInCache); @@ -31,6 +36,16 @@ internal static IEnumerator GetPrefabAsync(TaskResult gameObject, Pr private static IEnumerator InitPrefabAsync(TaskResult gameObject, PrefabInfo info, PrefabFactoryAsync prefabFactory) { + if (!ModPrefabCache.RunningPrefabs.Add(info.ClassID)) + { + yield return new WaitUntil(() => ModPrefabCache.RunningPrefabs.Contains(info.ClassID) is false); + if (ModPrefabCache.TryGetPrefabFromCache(info.ClassID, out var prefabInCache)) + { + gameObject.Set(prefabInCache); + yield break; + } + } + if (prefabFactory == null) { InternalLogger.Error($"PrefabHandler: Prefab Factory for {info.ClassID} is null!"); @@ -85,6 +100,7 @@ private static IEnumerator InitPrefabAsync(TaskResult gameObject, Pr gameObject.Set(obj); ModPrefabCache.AddPrefab(obj); + ModPrefabCache.RunningPrefabs.Remove(info.ClassID); } } diff --git a/Nautilus/Patchers/PrefabDatabasePatcher.cs b/Nautilus/Patchers/PrefabDatabasePatcher.cs index 93e05e59..925cd3d4 100644 --- a/Nautilus/Patchers/PrefabDatabasePatcher.cs +++ b/Nautilus/Patchers/PrefabDatabasePatcher.cs @@ -79,11 +79,6 @@ private static IPrefabRequest GetModPrefabAsync(string classId) return null; } - if(ModPrefabCache.Requests.TryGetValue(prefabInfo.ClassID, out var request)) - { - return request; - } - return new ModPrefabRequest(prefabInfo); }