public async Task LoginHandler(GameSession session, LoginRequestReqMessage message) { #region IPINFO var ipInfo = new IpInfo2(); try { //string info = new WebClient().DownloadString("" + session.RemoteEndPoint.Address); var info = new WebClient().DownloadString("http://ip-api.com/json/" + session.RemoteEndPoint.Address); ipInfo = JsonConvert.DeserializeObject <IpInfo2>(info); if (string.IsNullOrWhiteSpace(ipInfo.countryCode) || string.IsNullOrEmpty(ipInfo.countryCode)) { ipInfo.countryCode = "UNK"; } } catch (Exception) { ipInfo.countryCode = "UNK"; } #endregion Logger.ForAccount(message.AccountId, message.Username) .Information("GameServer login from {remoteEndPoint} : Country: {country}", session.RemoteEndPoint, ipInfo.countryCode); if (Config.Instance.BlockedCountries.ToList().Contains(ipInfo.countryCode) || Config.Instance .BlockedAddresses.ToList().Contains(session.RemoteEndPoint.Address.ToString())) { Logger.ForAccount(message.AccountId, message.Username) .Information("Denied connection from client in blocked country {country}", ipInfo.countryCode); await session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked)); return; } //if (message.Version != s_version) //{ // Logger.ForAccount(message.AccountId, message.Username) // .Error("Invalid client version {version}", message.Version); // // session.SendAsync(new LoginReguestAckMessage(GameLoginResult.WrongVersion)); // return; //} if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit) { Logger.ForAccount(message.AccountId, message.Username) .Error("Server is full"); await session.SendAsync(new LoginReguestAckMessage(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.ForAccount(message.AccountId, message.Username) .Error("Wrong login(account not existing)"); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); return; } var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}>"); var authsessionId = Hash.GetString <CRC32>($"<{accountDto.Username}+{sessionId}+{message.Datetime}>"); if (authsessionId != message.AuthToken) { Logger.ForAccount(message.AccountId, message.Username) .Error("Wrong sessionid(2)"); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); return; } var newsessionId = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>"); if (newsessionId != message.newToken) { Logger.ForAccount(message.AccountId, message.Username) .Error("Wrong sessionid(3)"); await session.SendAsync(new LoginReguestAckMessage(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.ForAccount(message.AccountId, message.Username) .Error("Banned until {unbanDate}", unbanDate); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); return; } var account = new Account(accountDto); #endregion if (account.SecurityLevel < Config.Instance.SecurityLevel) { Logger.ForAccount(account) .Error("No permission to enter this server({securityLevel} or above required)", Config.Instance.SecurityLevel); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.AuthenticationFailed)); return; } if (message.KickConnection) { Logger.ForAccount(account) .Information("Kicking old connection"); var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id); GameServer.Instance.PlayerManager.Remove(oldPlr); oldPlr?.Disconnect(); } if (GameServer.Instance.PlayerManager.Contains(account.Id)) { Logger.ForAccount(account) .Information("Kicking old connection"); var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id); GameServer.Instance.PlayerManager.Remove(oldPlr); oldPlr?.Disconnect(); } 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 <PlayerMailDto>(join => join.LeftOuterJoin()) .Include <PlayerSettingDto>(join => join.LeftOuterJoin()) .Where($"{nameof(PlayerDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); var expTable = GameServer.Instance.ResourceCache.GetExperience(); Experience expValue; if (plrDto == null) { // first time connecting to this server if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue)) { expValue = new Experience { TotalExperience = 0 }; Logger.Warning("Given start level is not found in the experience table"); } plrDto = new PlayerDto { Id = (int)account.Id, PlayTime = TimeSpan.FromSeconds(0).ToString(), 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 = expValue.TotalExperience }; await db.InsertAsync(plrDto); } else { if (!TimeSpan.TryParse(plrDto.PlayTime, out _)) { plrDto.PlayTime = TimeSpan.FromSeconds(0).ToString(); } if (plrDto.Level > 0 && plrDto.TotalExperience == 0) { if (!expTable.TryGetValue(plrDto.Level, out expValue)) { expValue = new Experience { TotalExperience = 0 }; Logger.Warning("Given level is not found in the experience table"); } plrDto.TotalExperience = expValue.TotalExperience - 1; await db.UpdateAsync(plrDto); } } plrDto.DeathMatchInfo = (List <PlayerDeathMatchDto>)(await db.FindAsync <PlayerDeathMatchDto>( statament => statament .Where($"{nameof(PlayerDeathMatchDto.PlayerId):C} = @PlayerId") .WithParameters(new { PlayerId = message.AccountId }))); plrDto.TouchDownInfo = (List <PlayerTouchDownDto>)(await db.FindAsync <PlayerTouchDownDto>( statament => statament .Where($"{nameof(PlayerTouchDownDto.PlayerId):C} = @PlayerId") .WithParameters(new { PlayerId = message.AccountId }))); plrDto.ChaserInfo = (List <PlayerChaserDto>)(await db.FindAsync <PlayerChaserDto>( statament => statament .Where($"{nameof(PlayerChaserDto.PlayerId):C} = @PlayerId") .WithParameters(new { PlayerId = message.AccountId }))); plrDto.BattleRoyalInfo = (List <PlayerBattleRoyalDto>)(await db.FindAsync <PlayerBattleRoyalDto>( statament => statament .Where($"{nameof(PlayerBattleRoyalDto.PlayerId):C} = @PlayerId") .WithParameters(new { PlayerId = message.AccountId }))); plrDto.CaptainInfo = (List <PlayerCaptainDto>)(await db.FindAsync <PlayerCaptainDto>( statament => statament .Where($"{nameof(PlayerCaptainDto.PlayerId):C} = @PlayerId") .WithParameters(new { PlayerId = message.AccountId }))); session.Player = new Player(session, account, plrDto); } if (session.Player == null) { return; } GameServer.Instance.PlayerManager.Add(session.Player); Logger.ForAccount(account) .Information("Login success for {0}", account.Username); var result = string.IsNullOrWhiteSpace(account.Nickname) ? GameLoginResult.ChooseNickname : GameLoginResult.OK; //if (result == GameLoginResult.ChooseNickname) //{ // session.Player.Account.Nickname = session.Player.Account.Username; // session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0); // using (var db = AuthDatabase.Open()) // { // var mapping = OrmConfiguration // .GetDefaultEntityMapping<AccountDto>() // .Clone() // .UpdatePropertiesExcluding(prop => prop.IsExcludedFromUpdates = true, // nameof(AccountDto.Nickname)); // await db.UpdateAsync( // new AccountDto // { // Id = (int) session.Player.Account.Id, // Nickname = session.Player.Account.Username // }, // statement => statement.WithEntityMappingOverride(mapping)); // } // Logger.ForAccount(account) // .Information($"Created Account for {session.Player.Account.Username}"); //} //else if (!session.Player.CharacterManager.CheckChars()) //{ // session.Player.CharacterManager.CreateFirst(0, 0, 0, 0, 0, 0); //} await session.SendAsync(new LoginReguestAckMessage(result, session.Player.Account.Id)); if (!string.IsNullOrWhiteSpace(account.Nickname)) { await LoginAsync(session); } }
public async Task LoginHandler(GameSession session, LoginRequestReqMessage message) { #region IPINFO var ipInfo = new IpInfo2(); try { var info = new WebClient().DownloadString("http://ip-api.com/json/" + session.RemoteEndPoint.Address); ipInfo = JsonConvert.DeserializeObject <IpInfo2>(info); if (string.IsNullOrWhiteSpace(ipInfo.countryCode) || string.IsNullOrEmpty(ipInfo.countryCode)) { ipInfo.countryCode = "UNK"; } } catch (Exception) { ipInfo.countryCode = "UNK"; } #endregion #region Validate Login AccountDto accountDto; using (var db = AuthDatabase.Open()) { accountDto = (await DbUtil.FindAsync <AccountDto>(db, statement => statement .Include <BanDto>(join => join.LeftOuterJoin()) .Where($"{nameof(AccountDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); } if (accountDto == null) { await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); await session.CloseAsync(); return; } message.AccountId = (ulong)accountDto.Id; message.Username = accountDto.Username; Logger.ForAccount(accountDto) .Information("GameServer login from {remoteEndPoint} : Country: {country}", session.RemoteEndPoint, ipInfo.countryCode); if (Config.Instance.BlockedCountries.ToList().Contains(ipInfo.countryCode)) { Logger.ForAccount(accountDto) .Warning("Denied connection from client in blocked country {country}", ipInfo.countryCode); await session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked)); await session.CloseAsync(); return; } if (Config.Instance.BlockedAddresses.ToList().Contains(session.RemoteEndPoint.Address.ToString())) { Logger.ForAccount(accountDto) .Warning("Denied connection from client of blocked ip {adress}", session.RemoteEndPoint); await session.SendAsync(new ServerResultAckMessage(ServerResult.IPLocked)); await session.CloseAsync(); return; } // if (message.Version != s_version) // { // Logger.ForAccount(message.AccountId, message.Username) // .Warning("Invalid client version {version}", message.Version); // // session.SendAsync(new LoginReguestAckMessage(GameLoginResult.WrongVersion)); // return; // } if (GameServer.Instance.PlayerManager.Count >= Config.Instance.PlayerLimit) { Logger.ForAccount(accountDto) .Warning("Server is full"); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.ServerFull)); await session.CloseAsync(); return; } var sessionId = Hash.GetUInt32 <CRC32>($"<{accountDto.Username}+{accountDto.Password}+{session.RemoteEndPoint.Address.MapToIPv4()}+{Config.Instance.AuthAPI.ApiKey}>"); var authsessionId = Hash.GetString <CRC32>($"<{accountDto.Username}+{sessionId}+{message.Datetime}>"); if (authsessionId != message.AuthToken) { Logger.ForAccount(accountDto) .Warning("Wrong sessionid(2)"); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); await session.CloseAsync(); return; } var newsessionId = Hash.GetString <CRC32>($"<{authsessionId}+{sessionId}>"); if (newsessionId != message.newToken) { Logger.ForAccount(accountDto) .Warning("Wrong sessionid(3)"); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); await session.CloseAsync(); 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.ForAccount(accountDto) .Warning("Banned until {unbanDate}", unbanDate); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.SessionTimeout)); await session.CloseAsync(); return; } var account = new Account(accountDto); #endregion if (account.SecurityLevel < Config.Instance.SecurityLevel) { Logger.ForAccount(account).Warning("No permission to enter this server({securityLevel} or above required)", Config.Instance.SecurityLevel); await session.SendAsync(new LoginReguestAckMessage(GameLoginResult.AuthenticationFailed)); await session.CloseAsync(); return; } if (GameServer.Instance.PlayerManager.Contains(account.Id)) { Logger.ForAccount(account) .Information("Kicking old connection"); var oldPlr = GameServer.Instance.PlayerManager.Get(account.Id); GameServer.Instance.PlayerManager.Remove(oldPlr); oldPlr?.Session.CloseAsync(); } Logger.ForAccount(account) .Information("Login success"); await Task.Run(async() => { using (var db = GameDatabase.Open()) { var plrDto = (await DbUtil.FindAsync <PlayerDto>(db, statement => statement .Include <PlayerCharacterDto>(join => join.LeftOuterJoin()) .Include <PlayerDenyDto>(join => join.LeftOuterJoin()) .Include <PlayerFriendDto>(join => join.LeftOuterJoin()) .Include <PlayerSettingDto>(join => join.LeftOuterJoin()) .Include <PlayerItemDto>(join => join.LeftOuterJoin()) .Include <PlayerMailDto>(join => join.LeftOuterJoin()) .Where($"{nameof(PlayerDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); var plrStatsDto = (await DbUtil.FindAsync <PlayerDto>(db, statement => statement .Include <PlayerDeathMatchDto>(join => join.LeftOuterJoin()) .Include <PlayerTouchDownDto>(join => join.LeftOuterJoin()) .Include <PlayerChaserDto>(join => join.LeftOuterJoin()) .Include <PlayerBattleRoyalDto>(join => join.LeftOuterJoin()) .Include <PlayerCaptainDto>(join => join.LeftOuterJoin()) .Where($"{nameof(PlayerDto.Id):C} = @Id") .WithParameters(new { Id = message.AccountId }))) .FirstOrDefault(); var expTable = GameServer.Instance.ResourceCache.GetExperience(); Experience expValue; if (plrDto == null) { // first time connecting to this server if (!expTable.TryGetValue(Config.Instance.Game.StartLevel, out expValue)) { expValue = new Experience { TotalExperience = 0 }; Logger.Warning("Given start level is not found in the experience table"); } plrDto = new PlayerDto { Id = (int)account.Id, PlayTime = TimeSpan.FromSeconds(0).ToString(), 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 = expValue.TotalExperience, }; try { await DbUtil.InsertAsync(db, plrDto); } catch (Exception e) { session.Channel.Pipeline.FireExceptionCaught(e); return; } } else { if (!TimeSpan.TryParse(plrDto.PlayTime, out _)) { plrDto.PlayTime = TimeSpan.FromSeconds(0).ToString(); } if (!expTable.TryGetValue(plrDto.Level, out expValue)) { expValue = new Experience { TotalExperience = 0 }; Logger.Warning("Given level is not found in the experience table"); } // Adjust total exp to correct range if (plrDto.TotalExperience < expValue.TotalExperience) { plrDto.TotalExperience = expValue.TotalExperience; await DbUtil.UpdateAsync(db, plrDto); } // Adjust total exp to minexp of current level if (plrDto.Level > 0 && plrDto.TotalExperience == 0) { plrDto.TotalExperience = expValue.TotalExperience - 1; await DbUtil.UpdateAsync(db, plrDto); } } if (plrStatsDto != null) { plrDto.DeathMatchInfo = plrStatsDto.DeathMatchInfo; plrDto.TouchDownInfo = plrStatsDto.TouchDownInfo; plrDto.ChaserInfo = plrStatsDto.ChaserInfo; plrDto.BattleRoyalInfo = plrStatsDto.BattleRoyalInfo; plrDto.CaptainInfo = plrStatsDto.CaptainInfo; } session.Player = new Player(session, account, plrDto); } if (session.Player == null) { Logger.ForAccount(account) .Error("PlayerInfo failed - Missing playerInstance"); return; } GameServer.Instance.PlayerManager.Add(session.Player); var result = string.IsNullOrWhiteSpace(account.Nickname) ? GameLoginResult.ChooseNickname : GameLoginResult.OK; result = session.Player.CharacterManager.Any() ? result : GameLoginResult.ChooseNickname; if (session.UpdateShop) { await ShopService.ShopUpdateMsg(session, false); session.UpdateShop = false; } await session.SendAsync(new LoginReguestAckMessage(result, session.Player.Account.Id)); if (result == GameLoginResult.OK) { await LoginAsync(session); } }); }