diff --git a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs index 7170823f..3a7f6660 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/ItemHelper.cs @@ -323,7 +323,7 @@ public class ItemHelper( /// is the tpl a descendant public bool IsOfBaseclass(MongoId tpl, MongoId baseClassTpl) { - return itemBaseClassService.ItemHasBaseClass(tpl, [baseClassTpl]); + return itemBaseClassService.ItemHasBaseClass(tpl, baseClassTpl); } /// diff --git a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs index 11fd6eef..568b123e 100644 --- a/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/ItemBaseClassService.cs @@ -17,8 +17,12 @@ public class ItemBaseClassService( ) { private bool _cacheGenerated; + + /// + /// Key = Item tpl, values = Ids of its parents + /// private Dictionary> _itemBaseClassesCache = []; - private HashSet rootNodeIds = []; + private readonly HashSet _rootNodeIds = []; /// /// Create cache and store inside ItemBaseClassService
@@ -44,7 +48,7 @@ public class ItemBaseClassService( } else { - rootNodeIds.Add(item.Key); + _rootNodeIds.Add(item.Key); } } @@ -89,7 +93,7 @@ public class ItemBaseClassService( // The cache is only generated for item templates with `_type == "Item"`, so return false for any other type, // including item templates that simply don't exist. - if (rootNodeIds.Contains(itemTpl)) + if (_rootNodeIds.Contains(itemTpl)) { return false; } @@ -123,12 +127,68 @@ public class ItemBaseClassService( return false; } + /// + /// Does item tpl inherit from the requested base class + /// + /// ItemTpl item to check base classes of + /// BaseClass base class to check for + /// true if item inherits from base class passed in + public bool ItemHasBaseClass(MongoId itemTpl, MongoId baseClasses) + { + if (!_cacheGenerated) + { + HydrateItemBaseClassCache(); + } + + if (itemTpl.IsEmpty()) + { + logger.Warning("Unable to check itemTpl base class as value passed is null"); + + return false; + } + + // The cache is only generated for item templates with `_type == "Item"`, so return false for any other type, + // including item templates that simply don't exist. + if (_rootNodeIds.Contains(itemTpl)) + { + return false; + } + + var existsInCache = _itemBaseClassesCache.TryGetValue(itemTpl, out var baseClassList); + if (!existsInCache) + { + // Not found + if (logger.IsLogEnabled(LogLevel.Debug)) + { + logger.Debug( + serverLocalisationService.GetText("baseclass-item_not_found", itemTpl) + ); + } + + // Not found in cache, Hydrate again - some mods add items late in server startup lifecycle + HydrateItemBaseClassCache(); + + existsInCache = _itemBaseClassesCache.TryGetValue(itemTpl, out baseClassList); + } + + if (existsInCache) + { + return baseClassList.Contains(baseClasses); + } + + logger.Warning( + serverLocalisationService.GetText("baseclass-item_not_found_failed", itemTpl) + ); + + return false; + } + /// /// Get base classes item inherits from /// /// ItemTpl item to get base classes for /// array of base classes - public List GetItemBaseClasses(MongoId itemTpl) + public HashSet GetItemBaseClasses(MongoId itemTpl) { if (!_cacheGenerated) { @@ -140,6 +200,6 @@ public class ItemBaseClassService( return []; } - return value.ToList(); + return value; } }