public async Task LoginHandler(GameSession session, CLoginReqMessage message) { Logger.Info() .Account(message.AccountId, message.Username) .Message($"Login from {session.RemoteEndPoint}") .Write(); if (message.Version != s_version) { Logger.Error() .Account(message.AccountId, message.Username) .Message($"Invalid client version {message.Version}") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.WrongVersion)); return; } if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Server is full") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.ServerFull)); return; } #region Validate Login AccountDto accountDto; using (var db = AuthDatabase.Open()) { accountDto = (await db.FindAsync <AccountDto>(statement => statement .Include <BanDto>(join => join.LeftOuterJoin()) .Where($"{nameof(AccountDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); } if (accountDto == null) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout)); return; } uint inputSessionId; if (!uint.TryParse(message.SessionId, out inputSessionId)) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout)); return; } var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>"); if (sessionId != inputSessionId) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout)); return; } var now = DateTimeOffset.Now.ToUnixTimeSeconds(); var ban = accountDto.Bans.FirstOrDefault(b => b.Date + (b.Duration ?? 0) > now); if (ban != null) { var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + (ban.Duration ?? 0)); Logger.Error() .Account(message.AccountId, message.Username) .Message($"Banned until {unbanDate}") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.SessionTimeout)); return; } var account = new Account(accountDto); #endregion if (account.SecurityLevel < Config.Instance.SecurityLevel) { Logger.Error() .Account(account) .Message($"No permission to enter this server({Config.Instance.SecurityLevel} or above required)") .Write(); session.SendAsync(new SLoginAckMessage((GameLoginResult)9)); return; } if (message.KickConnection) { Logger.Info() .Account(account) .Message("Kicking old connection") .Write(); var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id); oldPlr?.Disconnect(); } if (GameServer.Instance.PlayerManager.Contains(account.Id)) { Logger.Error() .Account(account) .Message("Already online") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.TerminateOtherConnection)); return; } using (var db = GameDatabase.Open()) { var plrDto = (await db.FindAsync <PlayerDto>(statement => statement .Include <PlayerCharacterDto>(join => join.LeftOuterJoin()) .Include <PlayerDenyDto>(join => join.LeftOuterJoin()) .Include <PlayerItemDto>(join => join.LeftOuterJoin()) .Include <PlayerLicenseDto>(join => join.LeftOuterJoin()) .Include <PlayerMailDto>(join => join.LeftOuterJoin()) .Include <PlayerSettingDto>(join => join.LeftOuterJoin()) .Where($"{nameof(PlayerDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); if (plrDto == null) { // first time connecting to this server var expTable = GameServer.Instance.ResourceCache.GetExperience(); Experience expValue; if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue)) { expValue = new Experience(); expValue.TotalExperience = 0; Logger.Warn($"Given start level is not found in the experience table"); } plrDto = new PlayerDto { Id = (int)account.Id, Level = Config.Instance.Game.StartLevel, PEN = Config.Instance.Game.StartPEN, AP = Config.Instance.Game.StartAP, Coins1 = Config.Instance.Game.StartCoins1, Coins2 = Config.Instance.Game.StartCoins2, TotalExperience = (int)expValue.TotalExperience }; await db.InsertAsync(plrDto); } session.Player = new Player(session, account, plrDto); } if (GameServer.Instance.PlayerManager.Contains(session.Player)) { session.Player = null; Logger.Error() .Account(account) .Message("Already online") .Write(); session.SendAsync(new SLoginAckMessage(GameLoginResult.TerminateOtherConnection)); return; } GameServer.Instance.PlayerManager.Add(session.Player); Logger.Info() .Account(account) .Message("Login success") .Write(); var result = string.IsNullOrWhiteSpace(account.Nickname) ? GameLoginResult.ChooseNickname : GameLoginResult.OK; await session.SendAsync(new SLoginAckMessage(result, session.Player.Account.Id)); if (!string.IsNullOrWhiteSpace(account.Nickname)) { await LoginAsync(session); } }
public async Task LoginHandler(GameServer server, GameSession session, CLoginReqMessage message) { Logger.Info() .Account(message.AccountId, message.Username) .Message("Login from {0}", ((TcpTransport)session.Transport).Socket.RemoteEndPoint) .Write(); if (message.Version != s_version) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Invalid client version {0}", message.Version) .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.WrongVersion }) .ConfigureAwait(false); return; } if (server.PlayerManager.Count >= Config.Instance.PlayerLimit) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Server is full") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.ServerFull }) .ConfigureAwait(false); return; } #region Validate Login var accountDto = await AuthDatabase.Instance.Accounts .FirstOrDefaultAsync(acc => acc.Id == (int)message.AccountId) .ConfigureAwait(false); if (accountDto == null) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.SessionTimeout }) .ConfigureAwait(false); return; } uint inputSessionId; if (!uint.TryParse(message.SessionId, out inputSessionId)) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.SessionTimeout }) .ConfigureAwait(false); return; } var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>"); if (sessionId != inputSessionId) { Logger.Error() .Account(message.AccountId, message.Username) .Message("Wrong login") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.SessionTimeout }) .ConfigureAwait(false); return; } var now = DateTimeOffset.Now.ToUnixTimeSeconds(); var ban = await accountDto.Bans.FirstOrDefaultAsync(b => b.Date + b.Duration > now) .ConfigureAwait(false); if (ban != null) { var unbanDate = DateTimeOffset.FromUnixTimeSeconds(ban.Date + ban.Duration); Logger.Error() .Account(message.AccountId, message.Username) .Message("Banned until {0}", unbanDate) .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.SessionTimeout }) .ConfigureAwait(false); return; } var account = new Account(accountDto); #endregion if (account.SecurityLevel < Config.Instance.SecurityLevel) { Logger.Error() .Account(account) .Message("No permission to enter this server({0} or above required)", Config.Instance.SecurityLevel) .Write(); await session.SendAsync(new SLoginAckMessage { Result = (GameLoginResult)9 }) .ConfigureAwait(false); return; } if (message.KickConnection) { Logger.Info() .Account(account) .Message("Kicking old connection") .Write(); var oldPlr = server.PlayerManager.Get(account.Id); oldPlr?.Disconnect(); } if (server.PlayerManager.Contains(account.Id)) { Logger.Error() .Account(account) .Message("Already online") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.TerminateOtherConnection }) .ConfigureAwait(false); return; } using (var scope = new DataAccessScope()) { var plrDto = await GameDatabase.Instance.Players .FirstOrDefaultAsync(p => p.Id == (int)account.Id) .ConfigureAwait(false); if (plrDto == null) { // first time connecting to this server plrDto = GameDatabase.Instance.Players.Create((int)account.Id); plrDto.Level = Config.Instance.Game.StartLevel; plrDto.PEN = Config.Instance.Game.StartPEN; plrDto.AP = Config.Instance.Game.StartAP; plrDto.Coins1 = Config.Instance.Game.StartCoins1; plrDto.Coins2 = Config.Instance.Game.StartCoins2; await scope.CompleteAsync() .ConfigureAwait(false); } session.Player = new Player(session, account, plrDto); } if (server.PlayerManager.Contains(session.Player)) { session.Player = null; Logger.Error() .Account(account) .Message("Already online") .Write(); await session.SendAsync(new SLoginAckMessage { Result = GameLoginResult.TerminateOtherConnection }) .ConfigureAwait(false); return; } server.PlayerManager.Add(session.Player); Logger.Info() .Account(account) .Message("Login success") .Write(); await session.SendAsync(new SLoginAckMessage { Result = string.IsNullOrWhiteSpace(account.Nickname) ? GameLoginResult.ChooseNickname : GameLoginResult.OK, AccountId = session.Player.Account.Id }).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(account.Nickname)) { await LoginAsync(server, session).ConfigureAwait(false); } }