// Copyright (c) 2023 Timothy Schenk. Subject to the GNU AGPL Version 3 License. using System.Collections.Concurrent; using Continuity.AuthServer.DB.Documents; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Wonderking.Game.Data; using Wonderking.Game.Reader; namespace Continuity.AuthServer.Services; public class ItemObjectPoolService : IHostedService { private readonly ConcurrentDictionary _itemObjectPool; private readonly ItemReader _itemReader; private readonly ILogger _logger; public ItemObjectPoolService(IConfiguration configuration, ILogger logger) { _logger = logger; _itemReader = new ItemReader(configuration.GetSection("Game").GetSection("Data").GetValue("Path") ?? string.Empty); _itemObjectPool = new ConcurrentDictionary(); } public Task StartAsync(CancellationToken cancellationToken) { var amountOfEntries = _itemReader.GetAmountOfEntries(); Parallel.For(0, (int)amountOfEntries, i => { var itemObject = _itemReader.GetEntry((uint)i); var result = _itemObjectPool.TryAdd(itemObject.ItemID, itemObject); if (!result) { throw new KeyNotFoundException($"Failed to add item {itemObject.ItemID} to the item object pool"); } _logger.LogTrace("Item with {ID} has been added", itemObject.ItemID); }); _logger.LogInformation("A total of {AmountOfEntries} items have been added to the item object pool", _itemObjectPool.Count); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } public ItemObject GetItem(ushort itemId) { _ = _itemObjectPool.TryGetValue(itemId, out var itemObject); return itemObject; } public bool ContainsItem(ushort itemId) { return _itemObjectPool.ContainsKey(itemId); } public IQueryable QueryItems() { return _itemObjectPool.AsReadOnly().Values.AsQueryable(); } public InventoryItem GetBaseInventoryItem(ushort itemId, ushort count = 1, bool isWorn = false) { var item = GetItem(itemId); return new InventoryItem { ItemId = itemId, Count = count, Slot = (byte)item.SlotNo1, InventoryTab = item.ItemType switch { 1 => InventoryTab.WornCashEquipment, 2 => isWorn ? InventoryTab.WornEquipment : InventoryTab.Equipment, 3 => InventoryTab.Etc, 4 => isWorn ? InventoryTab.WornCashEquipment : InventoryTab.Cash, 5 => InventoryTab.Warehouse, 0 => InventoryTab.WornEquipment, _ => InventoryTab.WornEquipment }, Level = item.MinimumLevelRequirement, Rarity = 0, AddOption = 0, AddOption2 = 0, AddOption3 = 0, Option = 0, Option2 = 0, Option3 = 0 }; } }