コード例 #1
0
        Task IMultiplayerClient.SettingsChanged(MultiplayerRoomSettings newSettings)
        {
            Debug.Assert(Room != null);
            Room.Settings = newSettings;

            return(Task.CompletedTask);
        }
コード例 #2
0
        private static void ensureSettingsModsValid(MultiplayerRoomSettings settings)
        {
            // check against ruleset
            if (!populateValidModsForRuleset(settings.RulesetID, settings.RequiredMods, out var requiredMods))
            {
                var invalidRequiredAcronyms = string.Join(',', settings.RequiredMods.Where(m => requiredMods.All(valid => valid.Acronym != m.Acronym)).Select(m => m.Acronym));
                throw new InvalidStateException($"Invalid mods were selected for specified ruleset: {invalidRequiredAcronyms}");
            }

            if (!populateValidModsForRuleset(settings.RulesetID, settings.AllowedMods, out var allowedMods))
            {
                var invalidAllowedAcronyms = string.Join(',', settings.AllowedMods.Where(m => allowedMods.All(valid => valid.Acronym != m.Acronym)).Select(m => m.Acronym));
                throw new InvalidStateException($"Invalid mods were selected for specified ruleset: {invalidAllowedAcronyms}");
            }

            if (!ModUtils.CheckCompatibleSet(requiredMods, out var invalid))
            {
                throw new InvalidStateException($"Invalid combination of required mods: {string.Join(',', invalid.Select(m => m.Acronym))}");
            }

            // check aggregate combinations with each allowed mod individually.
            foreach (var allowedMod in allowedMods)
            {
                if (!ModUtils.CheckCompatibleSet(requiredMods.Concat(new[] { allowedMod }), out invalid))
                {
                    throw new InvalidStateException($"Invalid combination of required and allowed mods: {string.Join(',', invalid.Select(m => m.Acronym))}");
                }
            }
        }
コード例 #3
0
        public async Task ChangeSettings(MultiplayerRoomSettings settings)
        {
            using (var userUsage = await GetOrCreateLocalUserState())
                using (var roomUsage = await getLocalUserRoom(userUsage.Item))
                {
                    var room = roomUsage.Item;

                    if (room == null)
                    {
                        throw new InvalidOperationException("Attempted to operate on a null room");
                    }

                    if (room.State != MultiplayerRoomState.Open)
                    {
                        throw new InvalidStateException("Attempted to change settings while game is active");
                    }

                    ensureIsHost(room);

                    // Server is authoritative over the playlist item ID.
                    // Todo: This needs to change for tournament mode.
                    settings.PlaylistItemId = room.Settings.PlaylistItemId;

                    if (room.Settings.Equals(settings))
                    {
                        return;
                    }

                    var previousSettings = room.Settings;

                    if (settings.RulesetID < 0 || settings.RulesetID > ILegacyRuleset.MAX_LEGACY_RULESET_ID)
                    {
                        throw new InvalidStateException("Attempted to select an unsupported ruleset.");
                    }

                    ensureSettingsModsValid(settings);

                    try
                    {
                        room.Settings = settings;
                        await updateDatabaseSettings(room);
                    }
                    catch
                    {
                        // rollback settings if an error occurred when updating the database.
                        room.Settings = previousSettings;
                        throw;
                    }

                    await ensureAllUsersValidMods(room);

                    // this should probably only happen for gameplay-related changes, but let's just keep things simple for now.
                    foreach (var u in room.Users.Where(u => u.State == MultiplayerUserState.Ready).ToArray())
                    {
                        await changeAndBroadcastUserState(room, u, MultiplayerUserState.Idle);
                    }

                    await Clients.Group(GetGroupId(room.RoomID)).SettingsChanged(settings);
                }
        }
コード例 #4
0
        public async Task ChangingSettingsMarksReadyUsersAsIdle()
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                Name            = "bestest room ever",
                BeatmapChecksum = "checksum"
            };

            await hub.JoinRoom(room_id);

            MultiplayerRoom?room;

            using (var usage = hub.GetRoom(room_id))
            {
                // unsafe, but just for tests.
                room = usage.Item;
                Debug.Assert(room != null);
            }

            await hub.ChangeState(MultiplayerUserState.Ready);

            mockReceiver.Verify(r => r.UserStateChanged(user_id, MultiplayerUserState.Ready), Times.Once);
            Assert.All(room.Users, u => Assert.Equal(MultiplayerUserState.Ready, u.State));

            await hub.ChangeSettings(testSettings);

            mockReceiver.Verify(r => r.UserStateChanged(user_id, MultiplayerUserState.Idle), Times.Once);
            Assert.All(room.Users, u => Assert.Equal(MultiplayerUserState.Idle, u.State));
        }
コード例 #5
0
        public override async Task ChangeSettings(MultiplayerRoomSettings settings)
        {
            Debug.Assert(Room != null);

            await((IMultiplayerClient)this).SettingsChanged(settings);

            foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready))
            {
                ChangeUserState(user.UserID, MultiplayerUserState.Idle);
            }
        }
コード例 #6
0
        public async Task ChangingSettingsToCustomRulesetThrows(int rulesetID)
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                BeatmapID       = 1234,
                BeatmapChecksum = "checksum",
                RulesetID       = rulesetID,
            };

            await hub.JoinRoom(room_id);

            await Assert.ThrowsAsync <InvalidStateException>(() => hub.ChangeSettings(testSettings));
        }
コード例 #7
0
        public async Task RoomSettingsUpdateNotifiesOtherUsers()
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                BeatmapID = 1234567,
                RulesetID = 2
            };

            await hub.JoinRoom(room_id);

            await hub.ChangeSettings(testSettings);

            mockReceiver.Verify(r => r.SettingsChanged(testSettings), Times.Once);
        }
コード例 #8
0
        public async Task ChangingSettingsToCustomizedBeatmapThrows()
        {
            mockDatabase.Setup(d => d.GetBeatmapChecksumAsync(9999)).ReturnsAsync("correct checksum");

            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                BeatmapID       = 9999,
                BeatmapChecksum = "incorrect checksum",
            };

            await hub.JoinRoom(room_id);

            await Assert.ThrowsAsync <InvalidStateException>(() => hub.ChangeSettings(testSettings));
        }
コード例 #9
0
        public async Task ChangingSettingsToNonExistentBeatmapThrows()
        {
            mockDatabase.Setup(d => d.GetBeatmapChecksumAsync(3333)).ReturnsAsync((string?)null);

            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                BeatmapID       = 3333,
                BeatmapChecksum = "checksum",
            };

            await hub.JoinRoom(room_id);

            await Assert.ThrowsAsync <InvalidStateException>(() => hub.ChangeSettings(testSettings));
        }
コード例 #10
0
        public async Task RoomSettingsUpdateNotifiesOtherUsers()
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                BeatmapID       = 1234567,
                BeatmapChecksum = "checksum",
                RulesetID       = 2
            };

            await Hub.JoinRoom(ROOM_ID);

            await Hub.ChangeSettings(testSettings);

            Receiver.Verify(r => r.SettingsChanged(testSettings), Times.Once);
        }
コード例 #11
0
        private void changeRoomSettings(MultiplayerRoomSettings settings)
        {
            multiplayerRoom.Settings = settings;

            // Changing settings should reset all user ready statuses.
            foreach (var user in multiplayerRoom.Users)
            {
                if (user.State == MultiplayerUserState.Ready)
                {
                    user.State = MultiplayerUserState.Idle;
                }
            }

            raiseRoomUpdated();
        }
コード例 #12
0
        public async Task ChangingSettingsUpdatesModel()
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                Name = "bestest room ever",
            };

            await hub.JoinRoom(room_id);

            await hub.ChangeSettings(testSettings);

            Assert.True(hub.TryGetRoom(room_id, out var room));

            Debug.Assert(room != null);
            Assert.Equal(testSettings.Name, room.Settings.Name);
        }
コード例 #13
0
        public async Task ChangeSettings(MultiplayerRoomSettings settings)
        {
            using (var userUsage = await GetOrCreateLocalUserState())
                using (var roomUsage = await getLocalUserRoom(userUsage.Item))
                {
                    var room = roomUsage.Item;

                    if (room == null)
                    {
                        throw new InvalidOperationException("Attempted to operate on a null room");
                    }

                    if (room.State != MultiplayerRoomState.Open)
                    {
                        throw new InvalidStateException("Attempted to change settings while game is active");
                    }

                    ensureIsHost(room);

                    if (room.Settings.Equals(settings))
                    {
                        return;
                    }

                    var previousSettings = room.Settings;

                    try
                    {
                        room.Settings = settings;
                        await updateDatabaseSettings(room);
                    }
                    catch
                    {
                        // rollback settings if an error occurred when updating the database.
                        room.Settings = previousSettings;
                        throw;
                    }

                    // this should probably only happen for gameplay-related changes, but let's just keep things simple for now.
                    foreach (var u in room.Users.Where(u => u.State == MultiplayerUserState.Ready).ToArray())
                    {
                        await changeAndBroadcastUserState(room, u, MultiplayerUserState.Idle);
                    }

                    await Clients.Group(GetGroupId(room.RoomID)).SettingsChanged(settings);
                }
        }
コード例 #14
0
        public override async Task ChangeSettings(MultiplayerRoomSettings settings)
        {
            Debug.Assert(Room != null);
            Debug.Assert(APIRoom != null);
            Debug.Assert(currentItem != null);

            // Server is authoritative for the time being.
            settings.PlaylistItemId = Room.Settings.PlaylistItemId;

            await changeQueueMode(settings.QueueMode).ConfigureAwait(false);

            await((IMultiplayerClient)this).SettingsChanged(settings).ConfigureAwait(false);

            foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready))
            {
                ChangeUserState(user.UserID, MultiplayerUserState.Idle);
            }

            await changeMatchType(settings.MatchType).ConfigureAwait(false);
        }
コード例 #15
0
        public async Task ChangingSettingsUpdatesModel()
        {
            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                Name            = "bestest room ever",
                BeatmapChecksum = "checksum"
            };

            await hub.JoinRoom(room_id);

            await hub.ChangeSettings(testSettings);

            using (var usage = hub.GetRoom(room_id))
            {
                var room = usage.Item;

                Debug.Assert(room != null);
                Assert.Equal(testSettings.Name, room.Settings.Name);
            }
        }
コード例 #16
0
        public async Task ChangeSettings(MultiplayerRoomSettings settings)
        {
            var room = await getLocalUserRoom();

            using (room.LockForUpdate())
            {
                if (room.State != MultiplayerRoomState.Open)
                {
                    throw new InvalidStateException("Attempted to change settings while game is active");
                }

                ensureIsHost(room);

                room.Settings = settings;

                await UpdateDatabaseSettings(room);

                await Clients.Group(GetGroupId(room.RoomID)).SettingsChanged(settings);
            }
        }
コード例 #17
0
        public async Task ServerDoesNotAcceptClientPlaylistItemId()
        {
            await hub.JoinRoom(room_id);

            MultiplayerRoomSettings testSettings = new MultiplayerRoomSettings
            {
                Name            = "bestest room ever",
                BeatmapChecksum = "checksum",
                PlaylistItemId  = 1
            };

            await hub.ChangeSettings(testSettings);

            using (var usage = hub.GetRoom(room_id))
            {
                var room = usage.Item;
                Debug.Assert(room != null);

                Assert.Equal(0, room.Settings.PlaylistItemId);
                mockReceiver.Verify(r => r.SettingsChanged(room.Settings), Times.Once);
            }
        }
コード例 #18
0
        public async Task ChangingRulesetRemovesInvalidUserMods()
        {
            await Hub.JoinRoom(ROOM_ID);

            var roomSettings = new MultiplayerRoomSettings
            {
                BeatmapChecksum = "checksum",
                AllowedMods     = new[]
                {
                    new APIMod(new OsuModApproachDifferent())
                },
            };

            await Hub.ChangeSettings(roomSettings);

            await Hub.ChangeUserMods(new[] { new APIMod(new OsuModApproachDifferent()) });

            using (var usage = Hub.GetRoom(ROOM_ID))
            {
                var room = usage.Item;
                Debug.Assert(room != null);
                Assert.NotEmpty(room.Users.First().Mods);
            }

            await Hub.ChangeSettings(new MultiplayerRoomSettings
            {
                RulesetID       = 2,
                BeatmapChecksum = "checksum",
            });

            using (var usage = Hub.GetRoom(ROOM_ID))
            {
                var room = usage.Item;
                Debug.Assert(room != null);
                Assert.Empty(room.Users.First().Mods);
            }
        }
コード例 #19
0
 public Task ChangeSettings(MultiplayerRoomSettings settings) =>
 connection.InvokeAsync(nameof(IMultiplayerServer.ChangeSettings), settings);