Exemplo n.º 1
0
        public async void HandleMessage(Client.Client sender, PacketReader stream)
        {
            if (sender == null)
            {
                throw new ArgumentNullException(nameof(sender));
            }

            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            try
            {
                int id = stream.ReadInt();

                //Projection against receiving the message again(which would be a client problem).
                if (sender.TryGetControlledNpc(out NpcInst controlledNpc))
                {
                    if (_Service.TryGetMapping(controlledNpc, out CharacterMapping characterMapping))
                    {
                        characterMapping.Character.RemoveMapping();
                    }
                    else
                    {
                        controlledNpc.Despawn();
                    }

                    _Log.Error($"A client send a {SupportedMessage} even through it does already control a npc. Trying to disconnect the player and remove the npc to get back into a defined state");
                    sender.Disconnect();
                    return;
                }

                //Get and map the selected character of the client.
                if (_AuthenticationService.TryGetSession(sender, out Session session))
                {
                    IList <Character> list = await _Service.GetAccountOwnedCharactersAsync(session.Account);

                    Character selectedChar = list.FirstOrDefault(c => c.CharacterId == id);

                    bool success = true;
                    JoinGameFailedReason failureReason = JoinGameFailedReason.None;


                    if (selectedChar == null)
                    {
                        //Invalid character id... return an error
                        success       = false;
                        failureReason = JoinGameFailedReason.InvalidCharacterId;
                    }
                    else
                    {
                        //Save the active character(this causes a database access).
                        await _Service.SetAccountActiveCharacterAsync(session.Account, selectedChar);

                        if (!selectedChar.TryGetMapping(out CharacterMapping mapping))
                        {
                            mapping = selectedChar.SpawnAndMap();
                        }

                        if (mapping.CharacterNpc.TryGetControllingClient(out Client.Client controllingClient))
                        {
                            //Character is in use by someone else.
                            success       = false;
                            failureReason = JoinGameFailedReason.CharacterInUse;
                        }
                        else
                        {
                            sender.SetControl(mapping.CharacterNpc);
                        }
                    }

                    //Send the result to the client.
                    using (var packet = _PacketWriterPool.GetScriptMessageStream(ScriptMessages.JoinGameResult))
                    {
                        packet.Write(success);
                        //Write the error code.
                        if (!success)
                        {
                            packet.Write((byte)failureReason);
                        }
                        sender.SendScriptMessage(packet, NetPriority.Medium, NetReliability.Reliable);
                    }
                }
            }
            catch (Exception e)
            {
                _Log.Error($"Something went wrong while handling a '{SupportedMessage}' script message. Disconnecting the client to get back into a defined state. Exception:  {e}");

                //Disconnect the client to get back into a defined state.
                sender.Disconnect();
            }
        }