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(); } }