diff --git a/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs b/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs index a6ac56465..6c1bc4c55 100644 --- a/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/Mod/CustomItemService.cs @@ -16,6 +16,7 @@ public class CustomItemService( DatabaseService databaseService, ItemHelper itemHelper, ItemBaseClassService itemBaseClassService, + ModItemCacheService modItemCacheService, ICloner cloner ) { @@ -72,6 +73,8 @@ public CreateItemResult CreateItemFromClone(NewItemFromCloneDetails newItemDetai AddToWeaponShelf(newItemId); } + modItemCacheService.AddModItem(Assembly.GetCallingAssembly(), newItemId); + result.Success = true; result.ItemId = newItemId; @@ -116,6 +119,8 @@ public CreateItemResult CreateItem(NewItemDetails newItemDetails) AddToWeaponShelf(newItem.Id); } + modItemCacheService.AddModItem(Assembly.GetCallingAssembly(), newItem.Id); + result.ItemId = newItemDetails.NewItem.Id; result.Success = true; diff --git a/Libraries/SPTarkov.Server.Core/Services/Mod/ModItemCacheService.cs b/Libraries/SPTarkov.Server.Core/Services/Mod/ModItemCacheService.cs new file mode 100644 index 000000000..34a1ce27c --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Services/Mod/ModItemCacheService.cs @@ -0,0 +1,84 @@ +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 modId) + { + var mod = GetModFromAssembly(caller); + if (mod is null) + { + logger.Error( + $"Could not find mod reference for assembly: {caller.GetName()} when adding item tpl: {modId.ToString()} to cache" + ); + return; + } + + var guid = mod.ModMetadata.ModGuid; + if (!_cachedItems.TryGetValue(guid, out _)) + { + _cachedItems.Add(guid, []); + } + + _cachedItems[guid].Add(modId); + + if (logger.IsLogEnabled(LogLevel.Debug)) + { + logger.Debug($"Mod: {guid} added item: {modId.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; + } +}