Exemple #1
0
        public void IfTheCreatorOfALobbyLeavesTheGameIsDestroyed()
        {
            var roomId = createRoom();

            // Have the host leave the lobby
            LeaveRoomRequest leaveRequest = new LeaveRoomRequest()
            {
                RoomId = roomId
            };

            LeaveRoomResponse leaveResponse = client.LeaveRoom(leaveRequest);

            Assert.AreEqual(leaveResponse.Status.IsSuccess, true);

            // Ensure that the player has left the game.
            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterLeave = client.GetOpenLobbies(new OpenLobbiesRequest());

            assertSuccessResponse(openLobbiesResponsAfterLeave.Status);
            Assert.AreEqual(0, openLobbiesResponsAfterLeave.Rooms.Count);

            // Ensure the player is not in the game.
            PlayerCurrentGamesResponse gamesResponse = client.GetPlayerCurrentGames(new PlayerCurrentGamesRequest());

            assertSuccessResponse(gamesResponse.Status);
            Assert.AreEqual(0, gamesResponse.Games.Count);
        }
Exemple #2
0
        /**
         * Leave a room the user is currently in.
         */
        public async Task <LeaveRoomResponse> LeaveRoom(LeaveRoomRequest payload)
        {
            try
            {
                var response = new LeaveRoomResponse();

                User user = await _userRepository.FindRoomOfUserById((Guid)payload.userIdentifier);

                if (user == null)
                {
                    throw new ApplicationError("[RoomService.LeaveRoom]", 1);
                }

                if (user.room == null)
                {
                    throw new ApplicationError("[RoomService.LeaveRoom]", 2);
                }

                var roomUsers = await _userRepository.FindAllByRoomId(user.room.id);

                user.room.users = roomUsers.Where(roomUser => roomUser.id != payload.userIdentifier).ToList();

                response.roomIdentifier = user.room.identifier;
                response.users          = user.room.users;

                await _unitOfWork.Save();

                return(response);
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public void IfTheCreatorOfALobbyLeavesTheGameNoPlayersAreStuckInTheLobby()
        {
            CreateRoomRequest createRequest = new CreateRoomRequest()
            {
                Anonymous          = false,
                Goal               = Goal.Domination,
                MaxPlayers         = 5,
                IsRanked           = false,
                RoomName           = "My Room!",
                AllowedSpecialists = { "a", "b", "c" },
            };

            CreateRoomResponse roomResponse = client.CreateNewRoom(createRequest);

            Assert.AreEqual(roomResponse.Status.IsSuccess, true);
            Assert.IsTrue(roomResponse.CreatedRoom.RoomId != null);
            var roomId = roomResponse.CreatedRoom.RoomId;

            // Have a player join the game
            authHelper.loginToAccount("userTwo");
            client.JoinRoom(new JoinRoomRequest()
            {
                RoomId = roomId,
            });

            authHelper.loginToAccount("userOne");
            // Have the host leave the lobby
            LeaveRoomRequest leaveRequest = new LeaveRoomRequest()
            {
                RoomId = roomId
            };

            LeaveRoomResponse leaveResponse = client.LeaveRoom(leaveRequest);

            Assert.AreEqual(leaveResponse.Status.IsSuccess, true);

            // Ensure that the player has left the game.
            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterLeave = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponsAfterLeave.Status.IsSuccess, true);
            Assert.AreEqual(0, openLobbiesResponsAfterLeave.Rooms.Count);

            // Ensure the player is not in the game.
            PlayerCurrentGamesResponse gamesResponse = client.GetPlayerCurrentGames(new PlayerCurrentGamesRequest());

            Assert.AreEqual(gamesResponse.Status.IsSuccess, true);
            Assert.AreEqual(0, gamesResponse.Games.Count);

            authHelper.loginToAccount("userTwo");
            // Ensure the player is not in the game.
            PlayerCurrentGamesResponse gamesTwoResponse = client.GetPlayerCurrentGames(new PlayerCurrentGamesRequest());

            Assert.AreEqual(gamesTwoResponse.Status.IsSuccess, true);
            Assert.AreEqual(0, gamesTwoResponse.Games.Count);
        }
Exemple #4
0
        public void Parse_Returns_Expected_Data(string roomName)
        {
            var builder = new MessageBuilder()
                          .WriteCode(MessageCode.Server.LeaveRoom)
                          .WriteString(roomName);

            var response = LeaveRoomResponse.FromByteArray(builder.Build());

            Assert.Equal(roomName, response.RoomName);
        }
Exemple #5
0
        public void PlayerCanLeaveAGameRoom()
        {
            CreateRoomResponse roomResponse = client.CreateNewRoom(createRoomRequest("My room!"));

            Assert.AreEqual(roomResponse.Status.IsSuccess, true);
            Assert.IsTrue(roomResponse.CreatedRoom.Id != null);
            var roomId = roomResponse.CreatedRoom.Id;

            authHelper.loginToAccount("userTwo");

            // View open rooms.
            OpenLobbiesResponse openLobbiesResponse = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponse.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponse.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponse.Rooms[0].Id);
            // Ensure the creator is a member of the game
            Assert.AreEqual(1, openLobbiesResponse.Rooms[0].Players.Count);
            Assert.AreEqual("userOne", openLobbiesResponse.Rooms[0].Players[0].Username);

            JoinRoomRequest joinRequest = new JoinRoomRequest()
            {
                RoomId = roomId,
            };

            JoinRoomResponse joinResponse = client.JoinRoom(joinRequest);

            Assert.AreEqual(joinResponse.Status.IsSuccess, true);

            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterJoin = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponsAfterJoin.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponsAfterJoin.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponsAfterJoin.Rooms[0].Id);
            Assert.AreEqual(2, openLobbiesResponsAfterJoin.Rooms[0].Players.Count);

            LeaveRoomRequest leaveRequest = new LeaveRoomRequest()
            {
                RoomId = roomId
            };

            LeaveRoomResponse leaveResponse = client.LeaveRoom(leaveRequest);

            Assert.AreEqual(leaveResponse.Status.IsSuccess, true);

            // Ensure that the player has left the game.
            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterLeave = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponsAfterLeave.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponsAfterLeave.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponsAfterLeave.Rooms[0].Id);
            Assert.AreEqual(1, openLobbiesResponsAfterLeave.Rooms[0].Players.Count);
        }
Exemple #6
0
        public void Parse_Throws_MessageException_On_Code_Mismatch()
        {
            var msg = new MessageBuilder()
                      .WriteCode(MessageCode.Server.JoinRoom)
                      .Build();

            var ex = Record.Exception(() => LeaveRoomResponse.FromByteArray(msg));

            Assert.NotNull(ex);
            Assert.IsType <MessageException>(ex);
        }
Exemple #7
0
        public void Parse_Throws_MessageReadException_On_Missing_Data()
        {
            var msg = new MessageBuilder()
                      .WriteCode(MessageCode.Server.LeaveRoom)
                      .WriteInteger(1)
                      .Build();

            var ex = Record.Exception(() => LeaveRoomResponse.FromByteArray(msg));

            Assert.NotNull(ex);
            Assert.IsType <MessageReadException>(ex);
        }
Exemple #8
0
        public HttpResponseMessage Leave([ModelBinder(typeof(JsonNetModelBinder))] LeaveRoomRequest request)
        {
            if (!Data.HasPlayer(request.PlayerId))
            {
                var leaveRoomFailedResponse = new LeaveRoomResponse()
                {
                    Result = false
                };
                return(new JsonNetResponseMessage(leaveRoomFailedResponse));
            }

            var player = Data.FindPlayer(request.PlayerId);

            if (player == null)
            {
                var leaveRoomFailedResponse = new LeaveRoomResponse()
                {
                    Result = false
                };
                return(new JsonNetResponseMessage(leaveRoomFailedResponse));
            }

            var  roomName = player.RoomName;
            Room room     = null;

            if (!Data.Rooms.TryGetValue(roomName, out room))
            {
                var leaveRoomFailedResponse = new LeaveRoomResponse()
                {
                    Result = false
                };
                return(new JsonNetResponseMessage(leaveRoomFailedResponse));
            }

            room.Players.Remove(player);

            var response = new LeaveRoomResponse()
            {
                Result = true
            };

            return(new JsonNetResponseMessage(response));
        }
Exemple #9
0
        public void IfTheCreatorOfALobbyLeavesTheGameNoPlayersAreStuckInTheLobby()
        {
            var roomId = createRoom();

            // Have a player join the game
            authHelper.loginToAccount("userTwo");
            client.JoinRoom(new JoinRoomRequest()
            {
                RoomId = roomId,
            });

            authHelper.loginToAccount("userOne");
            // Have the host leave the lobby
            LeaveRoomRequest leaveRequest = new LeaveRoomRequest()
            {
                RoomId = roomId
            };

            LeaveRoomResponse leaveResponse = client.LeaveRoom(leaveRequest);

            assertSuccessResponse(leaveResponse.Status);

            // Ensure that the player has left the game.
            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterLeave = client.GetOpenLobbies(new OpenLobbiesRequest());

            assertSuccessResponse(openLobbiesResponsAfterLeave.Status);
            Assert.AreEqual(0, openLobbiesResponsAfterLeave.Rooms.Count);

            // Ensure the player is not in the game.
            PlayerCurrentGamesResponse gamesResponse = client.GetPlayerCurrentGames(new PlayerCurrentGamesRequest());

            assertSuccessResponse(gamesResponse.Status);
            Assert.AreEqual(0, gamesResponse.Games.Count);

            authHelper.loginToAccount("userTwo");
            // Ensure the player is not in the game.
            PlayerCurrentGamesResponse gamesTwoResponse = client.GetPlayerCurrentGames(new PlayerCurrentGamesRequest());

            assertSuccessResponse(gamesTwoResponse.Status);
            Assert.AreEqual(0, gamesTwoResponse.Games.Count);
        }
Exemple #10
0
    //目前房主不能离开房间,房主只能解散房间,游戏开始之后就不能离开房间
    public void LeaveRoomClick()
    {
        Debug.Log("Leave Room Click");

        var game   = gamePlayController.game;
        var socket = gamePlayController.gameSocket;

        if (game.state != GameState.BeforeStart || Player.Me.userId == game.creater)
        {
            Debug.Log("game.state is not BeforeStart or I am room ceater, can't leave room");
            return;
        }

        //检查用户是否坐下座位上
        if (Player.Me.seat != null)
        {
            Debug.Log("Player.Me.seat is not null, can't leave room");
            return;
        }

        var req = new {
            userId     = Player.Me.userId,
            roomNo     = game.roomNo,
            clientInfo = Utils.GetClientInfo(),
            userInfo   = Utils.GetUserInfo()
        };

        socket.Emit(Messages.LeaveRoom, (s, packet, args) => {
            string msg = packet.ToString();
            Debug.Log("LeaveRoomResponse: " + msg);
            LeaveRoomResponse resp = JsonConvert.DeserializeObject <LeaveRoomResponse[]>(msg)[0];
            if (resp.status != 0)
            {
                return;
            }

            Scenes.Load("MainPage");
        }, JsonConvert.SerializeObject(req));

        setupGame.CloseMenuClick();
    }
Exemple #11
0
        /// <summary>
        ///     Handles incoming messages.
        /// </summary>
        /// <param name="sender">The <see cref="IMessageConnection"/> instance from which the message originated.</param>
        /// <param name="message">The message.</param>
        public async void HandleMessageRead(object sender, byte[] message)
        {
            var code = new MessageReader <MessageCode.Server>(message).ReadCode();

            if (code != MessageCode.Server.EmbeddedMessage)
            {
                Diagnostic.Debug($"Server message received: {code}");
            }

            try
            {
                switch (code)
                {
                case MessageCode.Server.ParentMinSpeed:
                case MessageCode.Server.ParentSpeedRatio:
                case MessageCode.Server.WishlistInterval:
                case MessageCode.Server.CheckPrivileges:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), IntegerResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomAdded:
                    PrivateRoomMembershipAdded?.Invoke(this, StringResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomRemoved:
                    var privateRoomRemoved = StringResponse.FromByteArray <MessageCode.Server>(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoved));
                    PrivateRoomMembershipRemoved?.Invoke(this, privateRoomRemoved);
                    break;

                case MessageCode.Server.PrivateRoomOperatorAdded:
                    PrivateRoomModerationAdded?.Invoke(this, StringResponse.FromByteArray <MessageCode.Server>(message));
                    break;

                case MessageCode.Server.PrivateRoomOperatorRemoved:
                    var privateRoomOperatorRemoved = StringResponse.FromByteArray <MessageCode.Server>(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomOperatorRemoved));
                    PrivateRoomModerationRemoved?.Invoke(this, privateRoomOperatorRemoved);
                    break;

                case MessageCode.Server.NewPassword:
                    var confirmedPassword = NewPassword.FromByteArray(message).Password;
                    SoulseekClient.Waiter.Complete(new WaitKey(code), confirmedPassword);
                    break;

                case MessageCode.Server.PrivateRoomToggle:
                    var acceptInvitations = PrivateRoomToggle.FromByteArray(message).AcceptInvitations;
                    SoulseekClient.Waiter.Complete(new WaitKey(code), acceptInvitations);
                    break;

                case MessageCode.Server.GlobalAdminMessage:
                    var msg = GlobalMessageNotification.FromByteArray(message);
                    GlobalMessageReceived?.Invoke(this, msg);
                    break;

                case MessageCode.Server.Ping:
                    SoulseekClient.Waiter.Complete(new WaitKey(code));
                    break;

                case MessageCode.Server.Login:
                    SoulseekClient.Waiter.Complete(new WaitKey(code), LoginResponse.FromByteArray(message));
                    break;

                case MessageCode.Server.RoomList:
                    var roomList = RoomListResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), roomList);
                    RoomListReceived?.Invoke(this, roomList);
                    break;

                case MessageCode.Server.PrivateRoomOwned:
                    var moderatedRoomInfo = PrivateRoomOwnedListNotification.FromByteArray(message);
                    PrivateRoomModeratedUserListReceived?.Invoke(this, moderatedRoomInfo);
                    break;

                case MessageCode.Server.PrivateRoomUsers:
                    var roomInfo = PrivateRoomUserListNotification.FromByteArray(message);
                    PrivateRoomUserListReceived?.Invoke(this, roomInfo);
                    break;

                case MessageCode.Server.PrivilegedUsers:
                    var privilegedUserList = PrivilegedUserListNotification.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code), privilegedUserList);
                    PrivilegedUserListReceived?.Invoke(this, privilegedUserList);
                    break;

                case MessageCode.Server.AddPrivilegedUser:
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(PrivilegedUserNotification.FromByteArray(message)));
                    break;

                case MessageCode.Server.NotifyPrivileges:
                    var pn = PrivilegeNotification.FromByteArray(message);
                    PrivilegeNotificationReceived?.Invoke(this, new PrivilegeNotificationReceivedEventArgs(pn.Username, pn.Id));

                    if (SoulseekClient.Options.AutoAcknowledgePrivilegeNotifications)
                    {
                        await SoulseekClient.AcknowledgePrivilegeNotificationAsync(pn.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.UserPrivileges:
                    var privilegeResponse = UserPrivilegeResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privilegeResponse.Username), privilegeResponse.IsPrivileged);
                    break;

                case MessageCode.Server.NetInfo:
                    var netInfo = NetInfoNotification.FromByteArray(message);

                    try
                    {
                        var parents = netInfo.Parents.Select(parent => (parent.Username, new IPEndPoint(parent.IPAddress, parent.Port)));
                        await SoulseekClient.DistributedConnectionManager.AddParentConnectionAsync(parents).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling NetInfo message: {ex.Message}");
                    }

                    break;

                case MessageCode.Server.CannotConnect:
                    var cannotConnect = CannotConnect.FromByteArray(message);
                    Diagnostic.Debug($"Received CannotConnect message for token {cannotConnect.Token}{(!string.IsNullOrEmpty(cannotConnect.Username) ? $" from user {cannotConnect.Username}" : string.Empty)}");

                    SoulseekClient.SearchResponder.TryDiscard(cannotConnect.Token);

                    if (!string.IsNullOrEmpty(cannotConnect.Username))
                    {
                        UserCannotConnect?.Invoke(this, new UserCannotConnectEventArgs(cannotConnect));
                    }

                    break;

                case MessageCode.Server.CannotJoinRoom:
                    var cannotJoinRoom = CannotJoinRoom.FromByteArray(message);
                    SoulseekClient.Waiter.Throw(
                        new WaitKey(MessageCode.Server.JoinRoom, cannotJoinRoom.RoomName),
                        new RoomJoinForbiddenException($"The server rejected the request to join room {cannotJoinRoom.RoomName}"));

                    break;

                case MessageCode.Server.ConnectToPeer:
                    var connectToPeerResponse = ConnectToPeerResponse.FromByteArray(message);

                    try
                    {
                        if (connectToPeerResponse.Type == Constants.ConnectionType.Transfer)
                        {
                            Diagnostic.Debug($"Received transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token}");

                            // ensure that we are expecting at least one file from this user before we connect. the response
                            // doesn't contain any other identifying information about the file.
                            if (!SoulseekClient.Downloads.IsEmpty && SoulseekClient.Downloads.Values.Any(d => d.Username == connectToPeerResponse.Username))
                            {
                                var(connection, remoteToken) = await SoulseekClient.PeerConnectionManager.GetTransferConnectionAsync(connectToPeerResponse).ConfigureAwait(false);

                                var download = SoulseekClient.Downloads.Values.FirstOrDefault(v => v.RemoteToken == remoteToken && v.Username == connectToPeerResponse.Username);

                                if (download != default(TransferInternal))
                                {
                                    Diagnostic.Debug($"Solicited inbound transfer connection to {download.Username} ({connection.IPEndPoint}) for token {download.Token} (remote: {download.RemoteToken}) established. (id: {connection.Id})");
                                    SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.IndirectTransfer, download.Username, download.Filename, download.RemoteToken), connection);
                                }
                                else
                                {
                                    Diagnostic.Debug($"Transfer ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}) for remote token {connectToPeerResponse.Token} does not match any waiting downloads, discarding.");
                                    connection.Disconnect("Unknown transfer");
                                }
                            }
                            else
                            {
                                throw new SoulseekClientException($"Unexpected transfer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}); Ignored");
                            }
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Peer)
                        {
                            Diagnostic.Debug($"Received message ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.PeerConnectionManager.GetOrAddMessageConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else if (connectToPeerResponse.Type == Constants.ConnectionType.Distributed)
                        {
                            Diagnostic.Debug($"Received distributed ConnectToPeer request from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint})");
                            await SoulseekClient.DistributedConnectionManager.GetOrAddChildConnectionAsync(connectToPeerResponse).ConfigureAwait(false);
                        }
                        else
                        {
                            throw new MessageException($"Unknown Connect To Peer connection type '{connectToPeerResponse.Type}'");
                        }
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Error handling ConnectToPeer response from {connectToPeerResponse.Username} ({connectToPeerResponse.IPEndPoint}): {ex.Message}");
                    }

                    break;

                case MessageCode.Server.AddUser:
                    var addUserResponse = AddUserResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, addUserResponse.Username), addUserResponse);
                    break;

                case MessageCode.Server.GetStatus:
                    var statsResponse = UserStatusResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, statsResponse.Username), statsResponse);
                    UserStatusChanged?.Invoke(this, new UserStatusChangedEventArgs(statsResponse));
                    break;

                case MessageCode.Server.PrivateMessage:
                    var pm = PrivateMessageNotification.FromByteArray(message);
                    PrivateMessageReceived?.Invoke(this, new PrivateMessageReceivedEventArgs(pm));

                    if (SoulseekClient.Options.AutoAcknowledgePrivateMessages)
                    {
                        await SoulseekClient.AcknowledgePrivateMessageAsync(pm.Id, CancellationToken.None).ConfigureAwait(false);
                    }

                    break;

                case MessageCode.Server.GetPeerAddress:
                    var peerAddressResponse = UserAddressResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, peerAddressResponse.Username), peerAddressResponse);
                    break;

                case MessageCode.Server.JoinRoom:
                    var roomData = JoinRoomResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, roomData.Name), roomData);
                    break;

                case MessageCode.Server.LeaveRoom:
                    var leaveRoomResponse = LeaveRoomResponse.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, leaveRoomResponse.RoomName));
                    break;

                case MessageCode.Server.SayInChatRoom:
                    var roomMessage = RoomMessageNotification.FromByteArray(message);
                    RoomMessageReceived?.Invoke(this, new RoomMessageReceivedEventArgs(roomMessage));
                    break;

                case MessageCode.Server.PublicChat:
                    var publicChatMessage = PublicChatMessageNotification.FromByteArray(message);
                    PublicChatMessageReceived?.Invoke(this, new PublicChatMessageReceivedEventArgs(publicChatMessage));
                    break;

                case MessageCode.Server.UserJoinedRoom:
                    var joinNotification = UserJoinedRoomNotification.FromByteArray(message);
                    RoomJoined?.Invoke(this, new RoomJoinedEventArgs(joinNotification));
                    break;

                case MessageCode.Server.UserLeftRoom:
                    var leftNotification = UserLeftRoomNotification.FromByteArray(message);
                    RoomLeft?.Invoke(this, new RoomLeftEventArgs(leftNotification));
                    break;

                case MessageCode.Server.RoomTickers:
                    var roomTickers = RoomTickerListNotification.FromByteArray(message);
                    RoomTickerListReceived?.Invoke(this, new RoomTickerListReceivedEventArgs(roomTickers));
                    break;

                case MessageCode.Server.RoomTickerAdd:
                    var roomTickerAdded = RoomTickerAddedNotification.FromByteArray(message);
                    RoomTickerAdded?.Invoke(this, new RoomTickerAddedEventArgs(roomTickerAdded.RoomName, roomTickerAdded.Ticker));
                    break;

                case MessageCode.Server.RoomTickerRemove:
                    var roomTickerRemoved = RoomTickerRemovedNotification.FromByteArray(message);
                    RoomTickerRemoved?.Invoke(this, new RoomTickerRemovedEventArgs(roomTickerRemoved.RoomName, roomTickerRemoved.Username));
                    break;

                case MessageCode.Server.PrivateRoomAddUser:
                    var privateRoomAddUserResponse = PrivateRoomAddUser.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomAddUserResponse.RoomName, privateRoomAddUserResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomRemoveUser:
                    var privateRoomRemoveUserResponse = PrivateRoomRemoveUser.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoveUserResponse.RoomName, privateRoomRemoveUserResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomAddOperator:
                    var privateRoomAddOperatorResponse = PrivateRoomAddOperator.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomAddOperatorResponse.RoomName, privateRoomAddOperatorResponse.Username));
                    break;

                case MessageCode.Server.PrivateRoomRemoveOperator:
                    var privateRoomRemoveOperatorResponse = PrivateRoomRemoveOperator.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(code, privateRoomRemoveOperatorResponse.RoomName, privateRoomRemoveOperatorResponse.Username));
                    break;

                case MessageCode.Server.KickedFromServer:
                    KickedFromServer?.Invoke(this, EventArgs.Empty);
                    break;

                case MessageCode.Server.FileSearch:
                    var searchRequest = ServerSearchRequest.FromByteArray(message);

                    // sometimes (most of the time?) a room search will result in a request to ourselves (assuming we are
                    // joined to it)
                    if (searchRequest.Username == SoulseekClient.Username)
                    {
                        break;
                    }

                    await SoulseekClient.SearchResponder.TryRespondAsync(searchRequest.Username, searchRequest.Token, searchRequest.Query).ConfigureAwait(false);

                    break;

                case MessageCode.Server.EmbeddedMessage:
                    SoulseekClient.DistributedMessageHandler.HandleEmbeddedMessage(message);
                    break;

                default:
                    Diagnostic.Debug($"Unhandled server message: {code}; {message.Length} bytes");
                    break;
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Warning($"Error handling server message: {code}; {ex.Message}", ex);
            }
        }
        public void PlayerCanLeaveAGameRoom()
        {
            CreateRoomRequest createRequest = new CreateRoomRequest()
            {
                Anonymous          = false,
                Goal               = Goal.Domination,
                MaxPlayers         = 5,
                IsRanked           = false,
                RoomName           = "My Room!",
                AllowedSpecialists = { "a", "b", "c" },
            };

            CreateRoomResponse roomResponse = client.CreateNewRoom(createRequest);

            Assert.AreEqual(roomResponse.Status.IsSuccess, true);
            Assert.IsTrue(roomResponse.CreatedRoom.RoomId != null);
            var roomId = roomResponse.CreatedRoom.RoomId;

            authHelper.loginToAccount("userTwo");

            // View open rooms.
            OpenLobbiesResponse openLobbiesResponse = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponse.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponse.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponse.Rooms[0].RoomId);
            // Ensure the creator is a member of the game
            Assert.AreEqual(1, openLobbiesResponse.Rooms[0].Players.Count);
            Assert.AreEqual("userOne", openLobbiesResponse.Rooms[0].Players[0].Username);

            JoinRoomRequest joinRequest = new JoinRoomRequest()
            {
                RoomId = roomId,
            };

            JoinRoomResponse joinResponse = client.JoinRoom(joinRequest);

            Assert.AreEqual(joinResponse.Status.IsSuccess, true);

            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterJoin = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponsAfterJoin.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponsAfterJoin.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponsAfterJoin.Rooms[0].RoomId);
            Assert.AreEqual(2, openLobbiesResponsAfterJoin.Rooms[0].Players.Count);

            LeaveRoomRequest leaveRequest = new LeaveRoomRequest()
            {
                RoomId = roomId
            };

            LeaveRoomResponse leaveResponse = client.LeaveRoom(leaveRequest);

            Assert.AreEqual(leaveResponse.Status.IsSuccess, true);

            // Ensure that the player has left the game.
            // View open rooms.
            OpenLobbiesResponse openLobbiesResponsAfterLeave = client.GetOpenLobbies(new OpenLobbiesRequest());

            Assert.AreEqual(openLobbiesResponsAfterLeave.Status.IsSuccess, true);
            Assert.AreEqual(1, openLobbiesResponsAfterLeave.Rooms.Count);
            Assert.AreEqual(roomId, openLobbiesResponsAfterLeave.Rooms[0].RoomId);
            Assert.AreEqual(1, openLobbiesResponsAfterLeave.Rooms[0].Players.Count);
        }