Skip to content

Commit

Permalink
feat: Ban custom prefabs from getting cached (SubnauticaModding#545)
Browse files Browse the repository at this point in the history
* Custom prefabs now can opt-out from cache

* Extension method for custom prefab to remove from cache

* Use taskResult instead of looking in cache

* Added more logs
  • Loading branch information
Metious authored May 6, 2024
1 parent 0167861 commit 1711ac2
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
32 changes: 32 additions & 0 deletions Nautilus/Assets/CustomPrefabExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Nautilus.Utility;

namespace Nautilus.Assets;

/// <summary>
/// Represents extension methods for the <see cref="CustomPrefab"/> class.
/// </summary>
public static class CustomPrefabExtensions
{
/// <summary>
/// Removes the current prefab from the prefab cache and doesn't allow it to get cached later.
/// </summary>
/// <param name="customPrefab">The custom prefab to remove from the prefab cache.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
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;
}
}
23 changes: 19 additions & 4 deletions Nautilus/Assets/ModPrefabCache.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Nautilus.Utility;
using System.Collections.Generic;
using Nautilus.Extensions;
using Nautilus.Handlers;
using UnityEngine;

namespace Nautilus.Assets;
Expand All @@ -16,7 +17,7 @@ public static class ModPrefabCache
private static ModPrefabCacheInstance _cacheInstance;

/// <summary> Adds the given prefab to the cache. </summary>
/// <param name="prefab"> The prefab object that is disabled and cached. </param>
/// <param name="prefab"> The prefab object that is disabled and cached.</param>
public static void AddPrefab(GameObject prefab)
{
EnsureCacheExists();
Expand All @@ -41,8 +42,12 @@ public static bool IsPrefabCached(string classId)
/// <remarks>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.<br/>Avoid using this method unless you know what you're doing.</remarks>
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);
}
Expand Down Expand Up @@ -74,7 +79,10 @@ private static void EnsureCacheExists()

internal class ModPrefabCacheInstance: MonoBehaviour
{
public Dictionary<string, GameObject> Entries { get; } = new Dictionary<string, GameObject>();
public Dictionary<string, GameObject> Entries { get; } = new();

// Prefabs that are banned from getting cached
internal static readonly HashSet<string> BannedPrefabs = new();

private Transform _prefabRoot;

Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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()
Expand Down
3 changes: 2 additions & 1 deletion Nautilus/Assets/ModPrefabRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -66,6 +66,7 @@ public bool MoveNext()
public void Reset()
{
task.Reset();
taskResult.Set(null);
Done = false;
}

Expand Down

0 comments on commit 1711ac2

Please sign in to comment.