Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
        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);
            }
        }