using System.Reflection; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Spt.Logging; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Models.Utils; namespace SPTarkov.Server.Core.Services.Mod; [Injectable(InjectionType.Singleton)] public class ModItemCacheService(ISptLogger logger, IReadOnlyList loadedMods) { private readonly Dictionary> _cachedItems = []; /// /// Get all mod items for a provided mod by GUID /// /// Guid of the mod to get the items for /// Hashset of mod items public IReadOnlySet GetCachedItemIdsFromMod(string guid) { return _cachedItems.TryGetValue(guid, out var modItems) ? modItems : []; } /// /// Get all items added by all mods. Key is mods guid and value is the items it has added /// /// All loaded mod items public IReadOnlyDictionary> GetAllCachedModItemIds() { return _cachedItems.ToDictionary>, string, IReadOnlySet>( modItem => modItem.Key, modItem => modItem.Value ); } /// /// Adds a mod item to the cache, internal use only. /// /// Callers assembly /// Item id added to database internal void AddModItem(Assembly caller, MongoId itemId) { var mod = GetModFromAssembly(caller); if (mod is null) { logger.Error( $"Could not find mod reference for assembly: {caller.GetName()} when adding item tpl: {itemId.ToString()} to cache" ); return; } var guid = mod.ModMetadata.ModGuid; if (!_cachedItems.TryGetValue(guid, out _)) { _cachedItems.Add(guid, []); } _cachedItems[guid].Add(itemId); if (logger.IsLogEnabled(LogLevel.Debug)) { logger.Debug($"Mod: {guid} added item: {itemId.ToString()} to database"); } } /// /// Get the SptMod object for the callers assembly /// /// Assembly adding the item id /// SptMod of the assembly private SptMod? GetModFromAssembly(Assembly caller) { foreach (var mod in loadedMods) { if (mod.Assemblies.Any(modAssembly => ReferenceEquals(caller, modAssembly))) { return mod; } } return null; } }