diff --git a/Nautilus/Assets/CustomPrefabExtensions.cs b/Nautilus/Assets/CustomPrefabExtensions.cs new file mode 100644 index 00000000..23081449 --- /dev/null +++ b/Nautilus/Assets/CustomPrefabExtensions.cs @@ -0,0 +1,32 @@ +using Nautilus.Utility; + +namespace Nautilus.Assets; + +/// +/// Represents extension methods for the class. +/// +public static class CustomPrefabExtensions +{ + /// + /// Removes the current prefab from the prefab cache and doesn't allow it to get cached later. + /// + /// The custom prefab to remove from the prefab cache. + /// A reference to this instance after the operation has completed. + public static ICustomPrefab RemoveFromCache(this CustomPrefab customPrefab) + { + if (customPrefab.Info == default) + { + return customPrefab; + } + + if (string.IsNullOrWhiteSpace(customPrefab.Info.ClassID)) + { + InternalLogger.Error($"Couldn't remove prefab '{customPrefab.Info}' from cache because the class ID is null."); + return customPrefab; + } + + ModPrefabCache.RemovePrefabFromCache(customPrefab.Info.ClassID); + + return customPrefab; + } +} \ No newline at end of file diff --git a/Nautilus/Assets/ModPrefabCache.cs b/Nautilus/Assets/ModPrefabCache.cs index f95564d4..df6a7a2a 100644 --- a/Nautilus/Assets/ModPrefabCache.cs +++ b/Nautilus/Assets/ModPrefabCache.cs @@ -1,6 +1,7 @@ using Nautilus.Utility; using System.Collections.Generic; using Nautilus.Extensions; +using Nautilus.Handlers; using UnityEngine; namespace Nautilus.Assets; @@ -16,7 +17,7 @@ public static class ModPrefabCache private static ModPrefabCacheInstance _cacheInstance; /// Adds the given prefab to the cache. - /// The prefab object that is disabled and cached. + /// The prefab object that is disabled and cached. public static void AddPrefab(GameObject prefab) { EnsureCacheExists(); @@ -41,8 +42,12 @@ public static bool IsPrefabCached(string classId) /// This operation is extremely dangerous on custom prefabs that are directly registering an asset bundle prefab as it may make the prefab unusable in the current session.
Avoid using this method unless you know what you're doing.
public static void RemovePrefabFromCache(string classId) { - if(_cacheInstance == null) + if (_cacheInstance == null) + { + InternalLogger.Debug($"Removed '{classId}' from prefab cache."); + ModPrefabCacheInstance.BannedPrefabs.Add(classId); return; + } _cacheInstance.RemoveCachedPrefab(classId); } @@ -74,7 +79,10 @@ private static void EnsureCacheExists() internal class ModPrefabCacheInstance: MonoBehaviour { - public Dictionary Entries { get; } = new Dictionary(); + public Dictionary Entries { get; } = new(); + + // Prefabs that are banned from getting cached + internal static readonly HashSet BannedPrefabs = new(); private Transform _prefabRoot; @@ -101,6 +109,11 @@ public void EnterPrefabIntoCache(GameObject prefab) return; } + if (BannedPrefabs.Contains(prefabIdentifier.classId)) + { + return; + } + if (!Entries.ContainsKey(prefabIdentifier.classId)) { Entries.Add(prefabIdentifier.classId, prefab); @@ -125,6 +138,8 @@ public void EnterPrefabIntoCache(GameObject prefab) public void RemoveCachedPrefab(string classId) { + BannedPrefabs.Add(classId); + if (!Entries.TryGetValue(classId, out var prefab)) { return; @@ -142,8 +157,8 @@ public void RemoveCachedPrefab(string classId) Destroy(prefab); } - InternalLogger.Debug($"ModPrefabCache: removing prefab '{classId}'"); Entries.Remove(classId); + InternalLogger.Debug($"ModPrefabCache: removing prefab '{classId}'"); } private void RemoveFakePrefabs() diff --git a/Nautilus/Assets/ModPrefabRequest.cs b/Nautilus/Assets/ModPrefabRequest.cs index 35e7d308..a20972e0 100644 --- a/Nautilus/Assets/ModPrefabRequest.cs +++ b/Nautilus/Assets/ModPrefabRequest.cs @@ -50,7 +50,7 @@ public object Current public bool TryGetPrefab(out GameObject result) { - return ModPrefabCache.TryGetPrefabFromCache(prefabInfo.ClassID, out result) && result != null; + return result = taskResult.Get(); } public bool MoveNext() @@ -66,6 +66,7 @@ public bool MoveNext() public void Reset() { task.Reset(); + taskResult.Set(null); Done = false; }