예제 #1
0
        private void updateUserPlayingState(int userId, MultiplayerUserState state)
        {
            bool wasPlaying = CurrentMatchPlayingUserIds.Contains(userId);
            bool isPlaying  = state >= MultiplayerUserState.WaitingForLoad && state <= MultiplayerUserState.FinishedPlay;

            if (isPlaying == wasPlaying)
            {
                return;
            }

            if (isPlaying)
            {
                CurrentMatchPlayingUserIds.Add(userId);
            }
            else
            {
                CurrentMatchPlayingUserIds.Remove(userId);
            }
        }
예제 #2
0
        public void ChangeUserState(int userId, MultiplayerUserState newState)
        {
            Debug.Assert(Room != null);
            ((IMultiplayerClient)this).UserStateChanged(userId, newState);

            Schedule(() =>
            {
                switch (Room.State)
                {
                case MultiplayerRoomState.WaitingForLoad:
                    if (Room.Users.All(u => u.State != MultiplayerUserState.WaitingForLoad))
                    {
                        foreach (var u in Room.Users.Where(u => u.State == MultiplayerUserState.Loaded))
                        {
                            ChangeUserState(u.UserID, MultiplayerUserState.Playing);
                        }

                        ((IMultiplayerClient)this).MatchStarted();

                        ChangeRoomState(MultiplayerRoomState.Playing);
                    }

                    break;

                case MultiplayerRoomState.Playing:
                    if (Room.Users.All(u => u.State != MultiplayerUserState.Playing))
                    {
                        foreach (var u in Room.Users.Where(u => u.State == MultiplayerUserState.FinishedPlay))
                        {
                            ChangeUserState(u.UserID, MultiplayerUserState.Results);
                        }
                        ChangeRoomState(MultiplayerRoomState.Open);

                        ((IMultiplayerClient)this).ResultsReady();

                        FinishCurrentItem().Wait();
                    }

                    break;
                }
            });
        }
예제 #3
0
        private void pressReadyButton(int?playingUserId = null)
        {
            // Can't use ClickButtonWhenEnabled<> due to needing to store the state after the button is enabled.

            AddUntilStep("wait for ready button to be enabled", () => readyButton.Enabled.Value);

            MultiplayerUserState lastState = MultiplayerUserState.Idle;
            MultiplayerRoomUser  user      = null;

            AddStep("click ready button", () =>
            {
                user      = playingUserId == null ? multiplayerClient.LocalUser : multiplayerClient.Room?.Users.Single(u => u.UserID == playingUserId);
                lastState = user?.State ?? MultiplayerUserState.Idle;

                InputManager.MoveMouseTo(readyButton);
                InputManager.Click(MouseButton.Left);
            });

            AddUntilStep("wait for state change", () => user?.State != lastState);
        }
예제 #4
0
        Task IMultiplayerClient.UserStateChanged(int userId, MultiplayerUserState state)
        {
            Scheduler.Add(() =>
            {
                var user = Room?.Users.SingleOrDefault(u => u.UserID == userId);

                // TODO: user should NEVER be null here, see https://github.com/ppy/osu/issues/17713.
                if (user == null)
                {
                    return;
                }

                user.State = state;
                updateUserPlayingState(userId, state);

                RoomUpdated?.Invoke();
            }, false);

            return(Task.CompletedTask);
        }
예제 #5
0
        public async Task ChangeState(MultiplayerUserState newState)
        {
            var room = await getLocalUserRoom();

            using (room.LockForUpdate())
            {
                var user = room.Users.Find(u => u.UserID == CurrentContextUserId);

                if (user == null)
                {
                    failWithInvalidState("Local user was not found in the expected room");
                }

                if (user.State == newState)
                {
                    return;
                }

                ensureValidStateSwitch(room, user.State, newState);
                user.State = newState;

                // handle whether this user should be receiving gameplay messages or not.
                switch (newState)
                {
                case MultiplayerUserState.Idle:
                    await Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupId(room.RoomID, true));

                    break;

                case MultiplayerUserState.Ready:
                    await Groups.AddToGroupAsync(Context.ConnectionId, GetGroupId(room.RoomID, true));

                    break;
                }

                await Clients.Group(GetGroupId(room.RoomID)).UserStateChanged(CurrentContextUserId, newState);

                await updateRoomStateIfRequired(room);
            }
        }
예제 #6
0
        Task IMultiplayerClient.UserStateChanged(int userId, MultiplayerUserState state)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

            Scheduler.Add(() =>
            {
                if (Room == null)
                {
                    return;
                }

                Room.Users.Single(u => u.UserID == userId).State = state;

                updateUserPlayingState(userId, state);

                RoomUpdated?.Invoke();
            }, false);

            return(Task.CompletedTask);
        }
예제 #7
0
 public override Task ChangeState(MultiplayerUserState newState)
 {
     ChangeUserState(api.LocalUser.Value.Id, newState);
     return(Task.CompletedTask);
 }
예제 #8
0
 public abstract Task ChangeState(MultiplayerUserState newState);
예제 #9
0
        private void ensureValidStateSwitch(MultiplayerRoom room, MultiplayerUserState oldState, MultiplayerUserState newState)
        {
            switch (newState)
            {
            case MultiplayerUserState.Idle:
                // any state can return to idle.
                break;

            case MultiplayerUserState.Ready:
                if (oldState != MultiplayerUserState.Idle)
                {
                    throw new InvalidStateChangeException(oldState, newState);
                }

                break;

            case MultiplayerUserState.WaitingForLoad:
                // state is managed by the server.
                throw new InvalidStateChangeException(oldState, newState);

            case MultiplayerUserState.Loaded:
                if (oldState != MultiplayerUserState.WaitingForLoad)
                {
                    throw new InvalidStateChangeException(oldState, newState);
                }

                break;

            case MultiplayerUserState.Playing:
                // state is managed by the server.
                throw new InvalidStateChangeException(oldState, newState);

            case MultiplayerUserState.FinishedPlay:
                if (oldState != MultiplayerUserState.Playing)
                {
                    throw new InvalidStateChangeException(oldState, newState);
                }

                break;

            case MultiplayerUserState.Results:
                // state is managed by the server.
                throw new InvalidStateChangeException(oldState, newState);

            case MultiplayerUserState.Spectating:
                if (oldState != MultiplayerUserState.Idle && oldState != MultiplayerUserState.Ready)
                {
                    throw new InvalidStateChangeException(oldState, newState);
                }

                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(newState), newState, null);
            }
        }
예제 #10
0
 private Task changeAndBroadcastUserState(MultiplayerRoom room, MultiplayerRoomUser user, MultiplayerUserState state)
 {
     user.State = state;
     return(Clients.Group(GetGroupId(room.RoomID)).UserStateChanged(user.UserID, user.State));
 }
예제 #11
0
 public Task ChangeState(MultiplayerUserState newState) =>
 connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState);
        public async Task UserCantChangeStateToReservedStates(MultiplayerUserState reservedState)
        {
            await hub.JoinRoom(room_id);

            await Assert.ThrowsAsync <InvalidStateChangeException>(() => hub.ChangeState(reservedState));
        }
예제 #13
0
 private void changeUserState(int userId, MultiplayerUserState newState)
 {
     multiplayerRoom.Users.Single(u => u.UserID == userId).State = newState;
     raiseRoomUpdated();
 }
예제 #14
0
 private void checkLocalUserState(MultiplayerUserState state) =>
 AddUntilStep($"local user is {state}", () => localUser.State == state);
예제 #15
0
 public InvalidStateChangeException(MultiplayerUserState oldState, MultiplayerUserState newState)
     : base($"Cannot change from {oldState} to {newState}")
 {
 }