server-master/srcs/_plugins/WingsEmu.Plugins.BasicImplementation/Miniland/MinilandManager.cs
2026-02-10 18:21:30 +01:00

183 lines
No EOL
6.8 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PhoenixLib.DAL.Redis.Locks;
using PhoenixLib.Logging;
using WingsAPI.Data.Miniland;
using WingsEmu.Game._enum;
using WingsEmu.Game.Configurations.Miniland;
using WingsEmu.Game.Managers;
using WingsEmu.Game.Maps;
using WingsEmu.Game.Miniland;
using WingsEmu.Game.Miniland.Events;
using WingsEmu.Game.Networking;
using WingsEmu.Plugins.BasicImplementations.Factories;
namespace WingsEmu.Plugins.BasicImplementations.Miniland;
public class MinilandManager : IMinilandManager
{
private readonly IExpirableLockService _expirableLock;
private readonly IMapDesignObjectFactory _mapDesignObjectFactory;
private readonly IMapManager _mapManager;
private readonly IMinigameManager _minigameManager;
private readonly Dictionary<long, int> _minilandCapacities = new();
private readonly MinilandConfiguration _minilandConfiguration;
private readonly ConcurrentDictionary<long, IMapInstance> _minilandInstances = new();
private readonly Dictionary<long, List<long>> _minilandInvitations = new();
private readonly ISessionManager _sessionManager;
public MinilandManager(IMapManager mapManager, IMapDesignObjectFactory mapDesignObjectFactory, ISessionManager sessionManager,
IMinigameManager minigameManager, MinilandConfiguration minilandConfiguration, IExpirableLockService expirableLock)
{
_mapManager = mapManager;
_mapDesignObjectFactory = mapDesignObjectFactory;
_sessionManager = sessionManager;
_minigameManager = minigameManager;
_minilandConfiguration = minilandConfiguration;
_expirableLock = expirableLock;
}
public async Task IncreaseMinilandVisitCounter(long characterId)
{
IClientSession session = _sessionManager.GetSessionByCharacterId(characterId);
await _expirableLock.TryIncrementTemporaryLockCounter($"game:locks:miniland-visit-counter:{characterId}", int.MaxValue, DateTime.UtcNow.Date.AddDays(1));
session.PlayerEntity.LifetimeStats.TotalMinilandVisits++;
}
public async Task<bool> CanRefreshDailyVisitCounter(long characterId) =>
await _expirableLock.TryAddTemporaryLockAsync($"game:locks:miniland-visit-counter:{characterId}", DateTime.UtcNow.Date.AddDays(1));
public async Task<int> GetMinilandVisitCounter(long characterId)
{
(bool exists, int counter) = await _expirableLock.TryGetTemporaryCounterValue($"game:locks:miniland-visit-counter:{characterId}");
return counter;
}
public IMapInstance CreateMinilandByCharacterSession(IClientSession session)
{
_minigameManager.RegisterInteraction(session, new MinilandInteractionInformationHolder(MinigameInteraction.None, default));
IMapInstance mapInstance = _mapManager.GenerateMapInstanceByMapId((int)MapIds.MINILAND, MapInstanceType.Miniland);
Game.Configurations.Miniland.Miniland minilandConfiguration = GetMinilandConfiguration(mapInstance);
SetMinilandCapacity(session.PlayerEntity.Id, minilandConfiguration.DefaultMaximumCapacity);
// It will remove object if somehow player doesn't have an item in inventory or the object just disappeared
List<CharacterMinilandObjectDto> toRemove = new();
foreach (CharacterMinilandObjectDto obj in session.PlayerEntity.MinilandObjects)
{
try
{
MapDesignObject mapObject = _mapDesignObjectFactory.CreateGameObject(session.PlayerEntity.Id, obj);
if (mapObject == null)
{
toRemove.Add(obj);
continue;
}
session.EmitEventAsync(new AddObjMinilandEndLogicEvent(mapObject, mapInstance));
}
catch (Exception e)
{
Log.Error("[MINILAND_MANAGER] Couldn't create map design object", e);
}
}
foreach (CharacterMinilandObjectDto obj in toRemove)
{
session.PlayerEntity.MinilandObjects.Remove(obj);
}
return !_minilandInstances.TryAdd(session.PlayerEntity.Id, mapInstance) ? null : mapInstance;
}
public IMapInstance GetMinilandByCharacterId(long characterId) => _minilandInstances.GetValueOrDefault(characterId);
public IClientSession GetSessionByMiniland(IMapInstance mapInstance)
{
foreach ((long characterId, IMapInstance instance) in _minilandInstances)
{
if (instance.Id == mapInstance.Id)
{
return _sessionManager.GetSessionByCharacterId(characterId);
}
}
return default;
}
public void SaveMinilandInvite(long senderId, long targetId)
{
if (!_minilandInvitations.TryGetValue(senderId, out List<long> invites))
{
invites = new List<long>();
_minilandInvitations[senderId] = invites;
}
invites.Add(targetId);
}
public bool ContainsMinilandInvite(long senderId) => _minilandInvitations.ContainsKey(senderId);
public bool ContainsTargetInvite(long senderId, long targetId) => _minilandInvitations.TryGetValue(senderId, out List<long> targetList) && targetList.Contains(targetId);
public void RemoveMinilandInvite(long senderId, long targetId)
{
if (!_minilandInvitations.TryGetValue(senderId, out List<long> invites))
{
invites = new List<long>();
}
invites.Remove(targetId);
}
public int GetMinilandMaximumCapacity(long characterId) => _minilandCapacities.TryGetValue(characterId, out int capacity) ? capacity : default;
public void RelativeUpdateMinilandCapacity(long characterId, int valueToAdd)
{
if (_minilandCapacities.TryAdd(characterId, valueToAdd))
{
return;
}
_minilandCapacities[characterId] += valueToAdd;
}
public Game.Configurations.Miniland.Miniland GetMinilandConfiguration(IMapInstance mapInstance)
{
if (mapInstance == null)
{
return null;
}
Game.Configurations.Miniland.Miniland minilandConfiguration = _minilandConfiguration.FirstOrDefault(x => x.MapVnum == mapInstance.MapId);
return minilandConfiguration;
}
public void RemoveMiniland(long characterId)
{
if (!_minilandInstances.TryGetValue(characterId, out IMapInstance miniland))
{
return;
}
_minilandInstances.TryRemove(characterId, out _);
_mapManager.RemoveMapInstance(miniland.Id);
miniland.Destroy();
}
private void SetMinilandCapacity(long characterId, int value)
{
if (_minilandCapacities.TryAdd(characterId, value))
{
return;
}
_minilandCapacities[characterId] = value;
}
}