Ejemplo n.º 1
0
        public async Task PlaylistItemAdded(MultiplayerPlaylistItem item)
        {
            if (Room == null)
            {
                return;
            }

            var playlistItem = await createPlaylistItem(item, true).ConfigureAwait(false);

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

                Debug.Assert(APIRoom != null);

                Room.Playlist.Add(item);
                APIRoom.Playlist.Add(playlistItem);

                ItemAdded?.Invoke(item);
                RoomUpdated?.Invoke();
            });
        }
Ejemplo n.º 2
0
        private void updateLocalRoomSettings(MultiplayerRoomSettings settings)
        {
            if (Room == null)
            {
                return;
            }

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

                Debug.Assert(apiRoom != null);

                // Update a few properties of the room instantaneously.
                Room.Settings      = settings;
                apiRoom.Name.Value = Room.Settings.Name;

                // The playlist update is delayed until an online beatmap lookup (below) succeeds.
                // In-order for the client to not display an outdated beatmap, the playlist is forcefully cleared here.
                apiRoom.Playlist.Clear();

                RoomUpdated?.Invoke();

                var req      = new GetBeatmapSetRequest(settings.BeatmapID, BeatmapSetLookupType.BeatmapId);
                req.Success += res => updatePlaylist(settings, res);

                api.Queue(req);
            }, false);
        }
Ejemplo n.º 3
0
    public async Task Initialize()
    {
        if (!_initialized)
        {
            _hubConnection = new HubConnectionBuilder()
                             .WithUrl(_hubUrl)
                             .Build();

            _hubConnection.On <string, string>("ReceiveMessage", (user, message) =>
                                               MessageReceived?.Invoke(user, message));

            _hubConnection.On <Room>("UpdatePlayerState", (room) =>
                                     PlayerStateUpdated?.Invoke(room));

            _hubConnection.On <Room>("RoomOpened", (room) =>
                                     RoomOpened?.Invoke(room));

            _hubConnection.On <Room>("UpdateRoom", (room) =>
                                     RoomUpdated?.Invoke(room));

            await _hubConnection.StartAsync();

            _initialized = true;
        }
    }
Ejemplo n.º 4
0
        Task IMultiplayerClient.HostChanged(int userId)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Debug.Assert(APIRoom != null);

                var user = Room.Users.FirstOrDefault(u => u.UserID == userId);

                Room.Host          = user;
                APIRoom.Host.Value = user?.User;

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 5
0
        public async Task PlaylistItemChanged(MultiplayerPlaylistItem item)
        {
            if (Room == null)
            {
                return;
            }

            var playlistItem = await createPlaylistItem(item).ConfigureAwait(false);

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

                Debug.Assert(APIRoom != null);

                Room.Playlist[Room.Playlist.IndexOf(Room.Playlist.Single(existing => existing.ID == item.ID))] = item;

                int existingIndex = APIRoom.Playlist.IndexOf(APIRoom.Playlist.Single(existing => existing.ID == item.ID));
                APIRoom.Playlist.RemoveAt(existingIndex);
                APIRoom.Playlist.Insert(existingIndex, playlistItem);

                // If the currently-selected item was the one that got replaced, update the selected item to the new one.
                if (CurrentMatchPlayingItem.Value?.ID == playlistItem.ID)
                {
                    CurrentMatchPlayingItem.Value = playlistItem;
                }

                RoomUpdated?.Invoke();
            });
        }
Ejemplo n.º 6
0
        private Task handleUserLeft(MultiplayerRoomUser user, Action <MultiplayerRoomUser>?callback)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Room.Users.Remove(user);
                PlayingUserIds.Remove(user.UserID);

                Debug.Assert(APIRoom != null);
                APIRoom.RecentParticipants.RemoveAll(u => u.Id == user.UserID);
                APIRoom.ParticipantCount.Value--;

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 7
0
        public Task PlaylistItemChanged(MultiplayerPlaylistItem item)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Debug.Assert(APIRoom != null);

                Room.Playlist[Room.Playlist.IndexOf(Room.Playlist.Single(existing => existing.ID == item.ID))] = item;

                int existingIndex = APIRoom.Playlist.IndexOf(APIRoom.Playlist.Single(existing => existing.ID == item.ID));
                APIRoom.Playlist.RemoveAt(existingIndex);
                APIRoom.Playlist.Insert(existingIndex, createPlaylistItem(item));

                ItemChanged?.Invoke(item);
                RoomUpdated?.Invoke();
            });

            return(Task.CompletedTask);
        }
Ejemplo n.º 8
0
        public Task PlaylistItemRemoved(long playlistItemId)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Debug.Assert(APIRoom != null);

                Room.Playlist.Remove(Room.Playlist.Single(existing => existing.ID == playlistItemId));
                APIRoom.Playlist.RemoveAll(existing => existing.ID == playlistItemId);

                ItemRemoved?.Invoke(playlistItemId);
                RoomUpdated?.Invoke();
            });

            return(Task.CompletedTask);
        }
        private Task updateLocalRoomSettings(MultiplayerRoomSettings settings, CancellationToken cancellationToken = default) => scheduleAsync(() =>
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(apiRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings      = settings;
            apiRoom.Name.Value = Room.Settings.Name;

            // The current item update is delayed until an online beatmap lookup (below) succeeds.
            // In-order for the client to not display an outdated beatmap, the current item is forcefully cleared here.
            CurrentMatchPlayingItem.Value = null;

            RoomUpdated?.Invoke();

            GetOnlineBeatmapSet(settings.BeatmapID, cancellationToken).ContinueWith(set => Schedule(() =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                updatePlaylist(settings, set.Result);
            }), TaskContinuationOptions.OnlyOnRanToCompletion);
        }, cancellationToken);
Ejemplo n.º 10
0
        public Task PlaylistItemAdded(MultiplayerPlaylistItem item)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Debug.Assert(APIRoom != null);

                Room.Playlist.Add(item);
                APIRoom.Playlist.Add(createPlaylistItem(item));

                ItemAdded?.Invoke(item);
                RoomUpdated?.Invoke();
            });

            return(Task.CompletedTask);
        }
Ejemplo n.º 11
0
        private Task updateLocalRoomSettings(MultiplayerRoomSettings settings, CancellationToken cancellationToken = default) => scheduleAsync(() =>
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(apiRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings      = settings;
            apiRoom.Name.Value = Room.Settings.Name;

            // The current item update is delayed until an online beatmap lookup (below) succeeds.
            // In-order for the client to not display an outdated beatmap, the current item is forcefully cleared here.
            CurrentMatchPlayingItem.Value = null;

            RoomUpdated?.Invoke();

            var req      = new GetBeatmapSetRequest(settings.BeatmapID, BeatmapSetLookupType.BeatmapId);
            req.Success += res =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                updatePlaylist(settings, res);
            };

            api.Queue(req);
        }, cancellationToken);
Ejemplo n.º 12
0
        public Task LeaveRoom()
        {
            // The join may have not completed yet, so certain tasks that either update the room or reference the room should be cancelled.
            // This includes the setting of Room itself along with the initial update of the room settings on join.
            joinCancellationSource?.Cancel();

            // Leaving rooms is expected to occur instantaneously whilst the operation is finalised in the background.
            // However a few members need to be reset immediately to prevent other components from entering invalid states whilst the operation hasn't yet completed.
            // For example, if a room was left and the user immediately pressed the "create room" button, then the user could be taken into the lobby if the value of Room is not reset in time.
            var scheduledReset = scheduleAsync(() =>
            {
                APIRoom = null;
                Room    = null;
                CurrentMatchPlayingItem.Value = null;
                PlayingUserIds.Clear();

                RoomUpdated?.Invoke();
            });

            return(joinOrLeaveTaskChain.Add(async() =>
            {
                await scheduledReset.ConfigureAwait(false);
                await LeaveRoomInternal().ConfigureAwait(false);
            }));
        }
Ejemplo n.º 13
0
        Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state)
        {
            Scheduler.Add(() =>
            {
                if (Room == null)
                {
                    return;
                }

                Debug.Assert(APIRoom != null);

                Room.State = state;

                switch (state)
                {
                case MultiplayerRoomState.Open:
                    APIRoom.Status.Value = new RoomStatusOpen();
                    break;

                case MultiplayerRoomState.Playing:
                    APIRoom.Status.Value = new RoomStatusPlaying();
                    break;

                case MultiplayerRoomState.Closed:
                    APIRoom.Status.Value = new RoomStatusEnded();
                    break;
                }

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 14
0
        public Task MatchEvent(MatchServerEvent e)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                switch (e)
                {
                case CountdownChangedEvent countdownChangedEvent:
                    Room.Countdown = countdownChangedEvent.Countdown;
                    break;
                }

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 15
0
        async Task IMultiplayerClient.UserJoined(MultiplayerRoomUser user)
        {
            if (Room == null)
            {
                return;
            }

            await PopulateUser(user).ConfigureAwait(false);

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

                // for sanity, ensure that there can be no duplicate users in the room user list.
                if (Room.Users.Any(existing => existing.UserID == user.UserID))
                {
                    return;
                }

                Room.Users.Add(user);

                addUserToAPIRoom(user);

                UserJoined?.Invoke(user);
                RoomUpdated?.Invoke();
            });
        }
Ejemplo n.º 16
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;

                if (state != MultiplayerUserState.Playing)
                {
                    PlayingUsers.Remove(userId);
                }

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 17
0
        public void onRoomUpdated(RoomUpdated roomUpdated)
        {
            Message message2 = new Message();

            message2.message = "<messageML> Hi " + roomUpdated.stream.roomName + "!</messageML>";
            MessageClient messageClient = new apiClientDotNet.MessageClient();

            messageClient.sendMessage(Program.symConfig, message2, roomUpdated.stream);
        }
Ejemplo n.º 18
0
        Task IMultiplayerClient.MatchRoomStateChanged(MatchRoomState state)
        {
            Scheduler.Add(() =>
            {
                if (Room == null)
                {
                    return;
                }

                Room.MatchState = state;
                RoomUpdated?.Invoke();
            }, false);

            return(Task.CompletedTask);
        }
Ejemplo n.º 19
0
        public virtual Task LeaveRoom()
        {
            Scheduler.Add(() =>
            {
                if (Room == null)
                {
                    return;
                }

                apiRoom = null;
                Room    = null;

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 20
0
        public virtual Task LeaveRoom()
        {
            Scheduler.Add(() =>
            {
                if (Room == null)
                {
                    return;
                }

                apiRoom = null;
                Room    = null;
                CurrentMatchPlayingUserIds.Clear();

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 21
0
        private void updateLocalRoomSettings(MultiplayerRoomSettings settings)
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(APIRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings           = settings;
            APIRoom.Name.Value      = Room.Settings.Name;
            APIRoom.Password.Value  = Room.Settings.Password;
            APIRoom.Type.Value      = Room.Settings.MatchType;
            APIRoom.QueueMode.Value = Room.Settings.QueueMode;

            RoomUpdated?.Invoke();
        }
Ejemplo n.º 22
0
        Task IMultiplayerClient.MatchUserStateChanged(int userId, MatchUserState 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.MatchState = state;
                RoomUpdated?.Invoke();
            }, false);

            return(Task.CompletedTask);
        }
Ejemplo n.º 23
0
        private void updateLocalRoomSettings(MultiplayerRoomSettings settings)
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(APIRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings           = settings;
            APIRoom.Name.Value      = Room.Settings.Name;
            APIRoom.Password.Value  = Room.Settings.Password;
            APIRoom.QueueMode.Value = Room.Settings.QueueMode;
            RoomUpdated?.Invoke();

            CurrentMatchPlayingItem.Value = APIRoom.Playlist.SingleOrDefault(p => p.ID == settings.PlaylistItemId);
        }
Ejemplo n.º 24
0
        Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability)
        {
            Scheduler.Add(() =>
            {
                var user = Room?.Users.SingleOrDefault(u => u.UserID == userId);

                // errors here are not critical - beatmap availability state is mostly for display.
                if (user == null)
                {
                    return;
                }

                user.BeatmapAvailability = beatmapAvailability;

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 25
0
        public Task UserModsChanged(int userId, IEnumerable <APIMod> mods)
        {
            Scheduler.Add(() =>
            {
                var user = Room?.Users.SingleOrDefault(u => u.UserID == userId);

                // errors here are not critical - user mods are mostly for display.
                if (user == null)
                {
                    return;
                }

                user.Mods = mods;

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Updates the local room settings with the given <see cref="MultiplayerRoomSettings"/>.
        /// </summary>
        /// <remarks>
        /// This updates both the joined <see cref="MultiplayerRoom"/> and the respective API <see cref="Room"/>.
        /// </remarks>
        /// <param name="settings">The new <see cref="MultiplayerRoomSettings"/> to update from.</param>
        private void updateLocalRoomSettings(MultiplayerRoomSettings settings)
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(APIRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings                     = settings;
            APIRoom.Name.Value                = Room.Settings.Name;
            APIRoom.Password.Value            = Room.Settings.Password;
            APIRoom.Type.Value                = Room.Settings.MatchType;
            APIRoom.QueueMode.Value           = Room.Settings.QueueMode;
            APIRoom.AutoStartDuration.Value   = Room.Settings.AutoStartDuration;
            APIRoom.CurrentPlaylistItem.Value = APIRoom.Playlist.Single(item => item.ID == settings.PlaylistItemId);

            RoomUpdated?.Invoke();
        }
Ejemplo n.º 27
0
        Task IMultiplayerClient.MatchUserStateChanged(int userId, MatchUserState state)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Room.Users.Single(u => u.UserID == userId).MatchState = state;
                RoomUpdated?.Invoke();
            }, false);

            return(Task.CompletedTask);
        }
Ejemplo n.º 28
0
        private Task updateLocalRoomSettings(MultiplayerRoomSettings settings, CancellationToken cancellationToken = default) => scheduleAsync(() =>
        {
            if (Room == null)
            {
                return;
            }

            Debug.Assert(APIRoom != null);

            // Update a few properties of the room instantaneously.
            Room.Settings          = settings;
            APIRoom.Name.Value     = Room.Settings.Name;
            APIRoom.Password.Value = Room.Settings.Password;

            // The current item update is delayed until an online beatmap lookup (below) succeeds.
            // In-order for the client to not display an outdated beatmap, the current item is forcefully cleared here.
            CurrentMatchPlayingItem.Value = null;

            RoomUpdated?.Invoke();

            GetOnlineBeatmapSet(settings.BeatmapID, cancellationToken).ContinueWith(task => Schedule(() =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                APIBeatmapSet beatmapSet = task.Result;

                // The incoming response is deserialised without circular reference handling currently.
                // Because we require using metadata from this instance, populate the nested beatmaps' sets manually here.
                foreach (var b in beatmapSet.Beatmaps)
                {
                    b.BeatmapSet = beatmapSet;
                }

                updatePlaylist(settings, beatmapSet);
            }), TaskContinuationOptions.OnlyOnRanToCompletion);
        }, cancellationToken);
        Task IMultiplayerClient.UserLeft(MultiplayerRoomUser user)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Room.Users.Remove(user);
                CurrentMatchPlayingUserIds.Remove(user.UserID);

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

            return(Task.CompletedTask);
        }
Ejemplo n.º 30
0
        private Task handleUserLeft(MultiplayerRoomUser user, Action <MultiplayerRoomUser>?callback)
        {
            if (Room == null)
            {
                return(Task.CompletedTask);
            }

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

                Room.Users.Remove(user);
                PlayingUserIds.Remove(user.UserID);

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

            return(Task.CompletedTask);
        }