146 lines
No EOL
6.1 KiB
C#
146 lines
No EOL
6.1 KiB
C#
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using PhoenixLib.Events;
|
|
using PhoenixLib.Logging;
|
|
using WingsAPI.Communication;
|
|
using WingsAPI.Communication.DbServer.CharacterService;
|
|
using WingsAPI.Communication.Sessions;
|
|
using WingsAPI.Communication.Sessions.Model;
|
|
using WingsAPI.Communication.Sessions.Request;
|
|
using WingsAPI.Communication.Sessions.Response;
|
|
using WingsEmu.Game.Characters.Events;
|
|
using WingsEmu.Game.Managers;
|
|
using WingsEmu.Game.Networking;
|
|
|
|
namespace WingsEmu.Plugins.BasicImplementations.Event.Characters;
|
|
|
|
public class CharacterPreLoadEventHandler : IAsyncEventProcessor<CharacterPreLoadEvent>
|
|
{
|
|
private static readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
|
|
private readonly ICharacterService _characterService;
|
|
private readonly IServerManager _serverManager;
|
|
private readonly ISessionManager _sessionManager;
|
|
private readonly ISessionService _sessionService;
|
|
|
|
|
|
public CharacterPreLoadEventHandler(ISessionService sessionService, ICharacterService characterService, IServerManager serverManager, ISessionManager sessionManager)
|
|
{
|
|
_sessionService = sessionService;
|
|
_characterService = characterService;
|
|
_serverManager = serverManager;
|
|
_sessionManager = sessionManager;
|
|
}
|
|
|
|
public async Task HandleAsync(CharacterPreLoadEvent e, CancellationToken cancellation)
|
|
{
|
|
await _semaphoreSlim.WaitAsync(cancellation);
|
|
try
|
|
{
|
|
IClientSession session = e.Sender;
|
|
if (session?.Account == null || session.HasSelectedCharacter)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SessionResponse sessionResponse = await _sessionService.GetSessionByAccountId(new GetSessionByAccountIdRequest { AccountId = session.Account.Id });
|
|
if (sessionResponse is not { ResponseType: RpcResponseType.SUCCESS })
|
|
{
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
Session sharedSession = sessionResponse.Session;
|
|
|
|
if (sharedSession.State != SessionState.CharacterSelection)
|
|
{
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
if (sharedSession.ChannelId != _serverManager.ChannelId)
|
|
{
|
|
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Wrong Channel: {sharedSession.AccountId} - {session.Account.MasterAccountId} - {sharedSession.HardwareId}");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
if (session.SessionId != sharedSession.EncryptionKey)
|
|
{
|
|
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Wrong Encryption Key: {sharedSession.AccountId} - {session.Account.MasterAccountId} - {sharedSession.HardwareId}");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
DbServerGetCharacterResponse response = await _characterService.GetCharacterBySlot(new DbServerGetCharacterFromSlotRequest
|
|
{
|
|
AccountId = session.Account.Id,
|
|
Slot = e.Slot
|
|
});
|
|
|
|
if (response.RpcResponseType != RpcResponseType.SUCCESS)
|
|
{
|
|
Log.Warn("[CHARACTER_SCREEN] Selected a character that does not exist");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
SessionResponse tmp = await _sessionService.ConnectCharacter(new ConnectCharacterRequest
|
|
{
|
|
AccountId = session.Account.Id,
|
|
ChannelId = _serverManager.ChannelId,
|
|
CharacterId = response.CharacterDto.Id
|
|
});
|
|
|
|
if (tmp.ResponseType != RpcResponseType.SUCCESS)
|
|
{
|
|
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Looks like {response.CharacterDto.Name} - {session.Account.MasterAccountId} - {sharedSession.HardwareId} was already connected and tried to connect to {_serverManager.ChannelId}");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
if (sharedSession.State == SessionState.CrossChannelAuthentication && _serverManager.ChannelId != sharedSession.AllowedCrossChannelId)
|
|
{
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
if (sharedSession.State != SessionState.CharacterSelection)
|
|
{
|
|
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Looks like accountId: {sharedSession.AccountId} - {response.CharacterDto.Name} - {sharedSession.HardwareId} was already connected on the channel while being on {_serverManager.ChannelId}");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
if (_sessionManager.IsOnline(response.CharacterDto.Id))
|
|
{
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
IClientSession alreadyConnectedSession = _sessionManager.GetSessionByCharacterId(response.CharacterDto.Id);
|
|
if (alreadyConnectedSession != null)
|
|
{
|
|
await alreadyConnectedSession.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Looks like {alreadyConnectedSession.PlayerEntity.Name} was already connected on the channel while being on {_serverManager.ChannelId}");
|
|
alreadyConnectedSession.ForceDisconnect();
|
|
|
|
await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.DANGER,
|
|
$"[POTENTIAL_DUPE][PRE_LOAD] Looks like {response.CharacterDto.Name} - {sharedSession.HardwareId} was already connected on the channel while being on {_serverManager.ChannelId}");
|
|
session.ForceDisconnect();
|
|
return;
|
|
}
|
|
|
|
session.SelectedCharacterSlot = e.Slot;
|
|
|
|
session.SendPacket("OK");
|
|
}
|
|
finally
|
|
{
|
|
_semaphoreSlim.Release();
|
|
}
|
|
}
|
|
} |