server-master/srcs/BazaarServer/Managers/BazaarManager.cs
2026-02-10 18:21:30 +01:00

186 lines
No EOL
6.5 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PhoenixLib.Caching;
using WingsAPI.Communication.Bazaar;
using WingsAPI.Data.Bazaar;
using WingsAPI.Game.Extensions.Bazaar;
using WingsAPI.Packets.Enums.Bazaar;
using WingsEmu.Core.Extensions;
using WingsEmu.Core.Generics;
using WingsEmu.DTOs.Bazaar;
namespace BazaarServer.Managers
{
public class BazaarManager
{
private readonly IBazaarItemDAO _bazaarItemDao;
private readonly BazaarSearchManager _bazaarSearchManager;
private readonly ILongKeyCachedRepository<BazaarItemDTO> _itemsCache;
private readonly ConcurrentDictionary<long, ThreadSafeHashSet<long>> _itemsIdsByCharacterId = new();
private readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
public BazaarManager(IBazaarItemDAO bazaarItemDao, ILongKeyCachedRepository<BazaarItemDTO> itemsCache, BazaarSearchManager bazaarSearchManager)
{
_bazaarItemDao = bazaarItemDao;
_itemsCache = itemsCache;
_bazaarSearchManager = bazaarSearchManager;
}
public async Task<long> CacheAllItemsInDb()
{
IEnumerable<BazaarItemDTO> items = await _bazaarItemDao.GetAllNonDeletedBazaarItems();
int count = 0;
foreach (BazaarItemDTO item in items)
{
AddToCache(item);
count++;
}
await _bazaarSearchManager.Initialize(items);
return count;
}
private void AddToCache(BazaarItemDTO item)
{
_itemsCache.Set(item.Id, item);
_itemsIdsByCharacterId.GetOrAdd(item.CharacterId, new ThreadSafeHashSet<long>()).Add(item.Id);
}
private void RemoveFromCache(BazaarItemDTO item)
{
_itemsCache.Remove(item.Id);
_itemsIdsByCharacterId.GetOrDefault(item.CharacterId)?.Remove(item.Id);
}
public async Task<BazaarItemDTO> SaveAsync(BazaarItemDTO item)
{
await _semaphoreSlim.WaitAsync();
try
{
BazaarItemDTO dto = await _bazaarItemDao.SaveAsync(item);
AddToCache(dto);
_bazaarSearchManager.AddItem(dto);
return dto;
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task<BazaarItemDTO> GetBazaarItemById(long bazaarItemId)
{
await _semaphoreSlim.WaitAsync();
try
{
return _itemsCache.Get(bazaarItemId);
}
finally
{
_semaphoreSlim.Release();
}
}
public ICollection<BazaarItemDTO> GetItemsByCharacterId(long characterId)
{
return _itemsIdsByCharacterId.GetOrDefault(characterId)?.Select(s => _itemsCache.Get(s)).ToList();
}
public async Task<BazaarItemDTO> DeleteItemWithDto(BazaarItemDTO item, long requesterCharacterId)
{
await _semaphoreSlim.WaitAsync();
try
{
BazaarItemDTO cachedItem = _itemsCache.Get(item.Id);
if (cachedItem == null || cachedItem.CharacterId != requesterCharacterId)
{
return null;
}
await _bazaarItemDao.DeleteByIdAsync(item.Id);
RemoveFromCache(item);
_bazaarSearchManager.RemoveItem(item);
return cachedItem;
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task<BazaarItemDTO> ChangeItemPriceWithDto(BazaarItemDTO bazaarItemDto, long characterId, long price, long saleFee)
{
await _semaphoreSlim.WaitAsync();
try
{
BazaarItemDTO cachedItem = _itemsCache.Get(bazaarItemDto.Id);
if (cachedItem == null || cachedItem.SoldAmount > 0 || characterId != cachedItem.CharacterId || cachedItem.GetBazaarItemStatus() != BazaarListedItemType.ForSale
|| BazaarExtensions.PriceOrAmountExceeds(bazaarItemDto.UsedMedal, price, bazaarItemDto.Amount))
{
return null;
}
cachedItem.PricePerItem = price;
cachedItem.SaleFee = saleFee;
BazaarItemDTO savedItem = await _bazaarItemDao.SaveAsync(cachedItem);
return savedItem;
}
finally
{
_semaphoreSlim.Release();
}
}
public IReadOnlyCollection<BazaarItemDTO> SearchBazaarItems(BazaarSearchContext bazaarSearchContext) => _bazaarSearchManager.SearchBazaarItems(bazaarSearchContext);
public async Task<BazaarItemDTO> BuyItemWithExpectedValues(long bazaarItemId, long buyerCharacterId, short amount, long pricePerItem)
{
await _semaphoreSlim.WaitAsync();
try
{
BazaarItemDTO cachedItem = _itemsCache.Get(bazaarItemId);
if (cachedItem == null || buyerCharacterId == cachedItem.CharacterId || amount < 1 || cachedItem.Amount - cachedItem.SoldAmount < amount || pricePerItem != cachedItem.PricePerItem
|| cachedItem.IsPackage && amount != cachedItem.Amount || cachedItem.GetBazaarItemStatus() != BazaarListedItemType.ForSale)
{
return null;
}
cachedItem.SoldAmount += amount;
BazaarItemDTO savedItem = await _bazaarItemDao.SaveAsync(cachedItem);
return savedItem;
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task<List<BazaarItemDTO>> UnlistItemsWithVnums(List<BazaarItemDTO> items)
{
await _semaphoreSlim.WaitAsync();
try
{
foreach (BazaarItemDTO bazaarItemDto in items)
{
bazaarItemDto.ExpiryDate = DateTime.UtcNow.AddDays(-1);
BazaarItemDTO dto = await _bazaarItemDao.SaveAsync(bazaarItemDto);
AddToCache(dto);
_bazaarSearchManager.AddItem(dto);
}
return items;
}
finally
{
_semaphoreSlim.Release();
}
}
}
}