using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using PhoenixLib.Caching; using PhoenixLib.Logging; using WingsAPI.Communication; using WingsAPI.Communication.DbServer.WarehouseService; using WingsAPI.Data.Account; using WingsAPI.Game.Extensions; using WingsEmu.Core.Extensions; using WingsEmu.DTOs.Items; using WingsEmu.Game._enum; using WingsEmu.Game.Warehouse; namespace WingsEmu.Plugins.BasicImplementations.Warehouse; public class AccountWarehouseManager : IAccountWarehouseManager { private static readonly TimeSpan LifeTime = TimeSpan.FromMinutes(15); private readonly IAccountWarehouseService _accountWarehouseService; private readonly ILongKeyCachedRepository> _cachedAccountItems; public AccountWarehouseManager(ILongKeyCachedRepository> cachedAccountItems, IAccountWarehouseService accountWarehouseService) { _cachedAccountItems = cachedAccountItems; _accountWarehouseService = accountWarehouseService; } public async Task<(IDictionary accountWarehouseItemDtos, ManagerResponseType?)> GetWarehouse(long accountId) { Dictionary retrievedItems = _cachedAccountItems.Get(accountId); if (retrievedItems != null) { _cachedAccountItems.Set(accountId, retrievedItems, LifeTime); return (retrievedItems, ManagerResponseType.Success); } AccountWarehouseGetItemsResponse response = null; try { response = await _accountWarehouseService.GetItems(new AccountWarehouseGetItemsRequest { AccountId = accountId }); } catch (Exception ex) { Log.Error("[ACCOUNT_WAREHOUSE_MANAGER][GET_ITEMS] ", ex); } Dictionary dictionary = response?.Items?.ToDictionary(x => x.Slot) ?? new Dictionary(); if (response?.ResponseType == RpcResponseType.SUCCESS) { _cachedAccountItems.Set(accountId, dictionary, LifeTime); } return (dictionary, response?.ResponseType.ToManagerType()); } public async Task<(AccountWarehouseItemDto, ManagerResponseType?)> GetWarehouseItem(long accountId, short slot) { (IDictionary familyWarehouseItemDtos, ManagerResponseType? responseType) = await GetWarehouse(accountId); return (familyWarehouseItemDtos.GetOrDefault(slot), responseType); } public async Task<(AccountWarehouseItemDto, ManagerResponseType?)> AddWarehouseItem(AccountWarehouseItemDto warehouseItemDtoToAdd) { AccountWarehouseAddItemResponse response = null; try { response = await _accountWarehouseService.AddItem(new AccountWarehouseAddItemRequest { Item = warehouseItemDtoToAdd }); } catch (Exception ex) { Log.Error("[ACCOUNT_WAREHOUSE_MANAGER][ADD_ITEM] ", ex); } if (response?.ResponseType == RpcResponseType.SUCCESS) { await UpdateWarehouseItem(warehouseItemDtoToAdd.AccountId, response.Item.Slot, response.Item); } return (response?.Item, response?.ResponseType.ToManagerType()); } public async Task<(AccountWarehouseItemDto, ItemInstanceDTO, ManagerResponseType?)> WithdrawWarehouseItem(AccountWarehouseItemDto warehouseItemDtoToWithdraw, int amount) { AccountWarehouseWithdrawItemResponse response = null; try { response = await _accountWarehouseService.WithdrawItem(new AccountWarehouseWithdrawItemRequest { ItemToWithdraw = warehouseItemDtoToWithdraw, Amount = amount }); } catch (Exception ex) { Log.Error("[ACCOUNT_WAREHOUSE_MANAGER][WITHDRAW_ITEM] ", ex); } if (response?.ResponseType == RpcResponseType.SUCCESS) { await UpdateWarehouseItem(warehouseItemDtoToWithdraw.AccountId, warehouseItemDtoToWithdraw.Slot, response.UpdatedItem); } return (response?.UpdatedItem, response?.WithdrawnItem, response?.ResponseType.ToManagerType()); } public async Task<(AccountWarehouseItemDto oldItem, AccountWarehouseItemDto newItem, ManagerResponseType?)> MoveWarehouseItem(AccountWarehouseItemDto warehouseItemDtoToMove, int amount, short newSlot) { AccountWarehouseMoveItemResponse response = null; try { response = await _accountWarehouseService.MoveItem(new AccountWarehouseMoveItemRequest { WarehouseItemDtoToMove = warehouseItemDtoToMove, Amount = amount, NewSlot = newSlot }); } catch (Exception ex) { Log.Error("[ACCOUNT_WAREHOUSE_MANAGER][MOVE_ITEM] ", ex); } if (response?.ResponseType == RpcResponseType.SUCCESS) { await UpdateWarehouseItem(warehouseItemDtoToMove.AccountId, warehouseItemDtoToMove.Slot, response.OldItem); await UpdateWarehouseItem(warehouseItemDtoToMove.AccountId, newSlot, response.NewItem); } return (response?.OldItem, response?.NewItem, response?.ResponseType.ToManagerType()); } public void CleanCache(long accountId) { _cachedAccountItems.Remove(accountId); } private async Task UpdateWarehouseItem(long accountId, short slot, AccountWarehouseItemDto dto) { (IDictionary items, ManagerResponseType? responseType) = await GetWarehouse(accountId); if (responseType != ManagerResponseType.Success) { return; } if (dto == null) { items.Remove(slot); return; } items[slot] = dto; } }