1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-05 10:33:22 +08:00

Merge pull request #30807 from smoogipoo/multiplayer-nrt

Enable NRT for multiplayer and playlists
This commit is contained in:
Bartłomiej Dach 2024-11-22 08:50:11 +01:00 committed by GitHub
commit ce3d4e8648
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 361 additions and 417 deletions

View File

@ -73,7 +73,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddStep("create room initially in gameplay", () =>
{
var newRoom = new Room();
newRoom.CopyFrom(SelectedRoom.Value);
newRoom.CopyFrom(SelectedRoom.Value!);
newRoom.RoomID = null;
MultiplayerClient.RoomSetupAction = room =>

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using NUnit.Framework;
@ -21,12 +19,12 @@ namespace osu.Game.Tests.OnlinePlay
[HeadlessTest]
public partial class TestSceneCatchUpSyncManager : OsuTestScene
{
private GameplayClockContainer master;
private SpectatorSyncManager syncManager;
private GameplayClockContainer master = null!;
private SpectatorSyncManager syncManager = null!;
private Dictionary<SpectatorPlayerClock, int> clocksById;
private SpectatorPlayerClock player1;
private SpectatorPlayerClock player2;
private Dictionary<SpectatorPlayerClock, int> clocksById = null!;
private SpectatorPlayerClock player1 = null!;
private SpectatorPlayerClock player2 = null!;
[SetUp]
public void Setup()

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
@ -31,7 +29,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected readonly BindableList<MultiplayerRoomUser> MultiplayerUsers = new BindableList<MultiplayerRoomUser>();
protected MultiplayerGameplayLeaderboard Leaderboard { get; private set; }
protected MultiplayerGameplayLeaderboard? Leaderboard { get; private set; }
protected virtual MultiplayerRoomUser CreateUser(int userId) => new MultiplayerRoomUser(userId);
@ -40,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
private readonly BindableList<int> multiplayerUserIds = new BindableList<int>();
private readonly BindableDictionary<int, SpectatorState> watchedUserStates = new BindableDictionary<int, SpectatorState>();
private OsuConfigManager config;
private OsuConfigManager config = null!;
private readonly Mock<SpectatorClient> spectatorClient = new Mock<SpectatorClient>();
private readonly Mock<MultiplayerClient> multiplayerClient = new Mock<MultiplayerClient>();
@ -133,7 +131,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
LoadComponentAsync(Leaderboard = CreateLeaderboard(), Add);
});
AddUntilStep("wait for load", () => Leaderboard.IsLoaded);
AddUntilStep("wait for load", () => Leaderboard!.IsLoaded);
AddStep("check watch requests were sent", () =>
{
@ -146,7 +144,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void TestScoreUpdates()
{
AddRepeatStep("update state", UpdateUserStatesRandomly, 100);
AddToggleStep("switch compact mode", expanded => Leaderboard.Expanded.Value = expanded);
AddToggleStep("switch compact mode", expanded => Leaderboard!.Expanded.Value = expanded);
}
[Test]

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using NUnit.Framework;
using osu.Framework.Graphics;
@ -12,7 +10,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneCreateMultiplayerMatchButton : MultiplayerTestScene
{
private CreateMultiplayerMatchButton button;
private CreateMultiplayerMatchButton button = null!;
public override void SetUpSteps()
{
@ -29,7 +27,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestButtonEnableStateChanges()
{
IDisposable joiningRoomOperation = null;
IDisposable joiningRoomOperation = null!;
assertButtonEnableState(true);

View File

@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("4 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 4);
AddAssert("46 hidden users", () => list.ChildrenOfType<DrawableRoomParticipantsList.HiddenUserCount>().Single().Count == 46);
AddStep("remove from end", () => removeUserAt(SelectedRoom.Value.RecentParticipants.Count - 1));
AddStep("remove from end", () => removeUserAt(SelectedRoom.Value!.RecentParticipants.Count - 1));
AddAssert("4 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 4);
AddAssert("45 hidden users", () => list.ChildrenOfType<DrawableRoomParticipantsList.HiddenUserCount>().Single().Count == 45);
@ -138,18 +138,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void addUser(int id)
{
SelectedRoom.Value.RecentParticipants = SelectedRoom.Value.RecentParticipants.Append(new APIUser
SelectedRoom.Value!.RecentParticipants = SelectedRoom.Value!.RecentParticipants.Append(new APIUser
{
Id = id,
Username = $"User {id}"
}).ToArray();
SelectedRoom.Value.ParticipantCount++;
SelectedRoom.Value!.ParticipantCount++;
}
private void removeUserAt(int index)
{
SelectedRoom.Value.RecentParticipants = SelectedRoom.Value.RecentParticipants.Where(u => !u.Equals(SelectedRoom.Value.RecentParticipants[index])).ToArray();
SelectedRoom.Value.ParticipantCount--;
SelectedRoom.Value!.RecentParticipants = SelectedRoom.Value!.RecentParticipants.Where(u => !u.Equals(SelectedRoom.Value!.RecentParticipants[index])).ToArray();
SelectedRoom.Value!.ParticipantCount--;
}
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -39,9 +37,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneDrawableRoomPlaylist : MultiplayerTestScene
{
private TestPlaylist playlist;
private BeatmapManager manager;
private TestPlaylist playlist = null!;
private BeatmapManager manager = null!;
[BackgroundDependencyLoader]
private void load(GameHost host, AudioManager audio)
@ -199,14 +196,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestDownloadButtonHiddenWhenBeatmapExists()
{
Live<BeatmapSetInfo> imported = null;
Live<BeatmapSetInfo> imported = null!;
AddStep("import beatmap", () =>
{
var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo;
Debug.Assert(beatmap.BeatmapSet != null);
imported = manager.Import(beatmap.BeatmapSet);
imported = manager.Import(beatmap.BeatmapSet)!;
});
createPlaylistWithBeatmaps(() => imported.PerformRead(s => s.Beatmaps.Detach()));
@ -378,7 +375,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
}
});
private void createPlaylist(Action<TestPlaylist> setupPlaylist = null)
private void createPlaylist(Action<TestPlaylist>? setupPlaylist = null)
{
AddStep("create playlist", () =>
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
@ -26,9 +24,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneFreeModSelectOverlay : MultiplayerTestScene
{
private FreeModSelectOverlay freeModSelectOverlay;
private FooterButtonFreeMods footerButtonFreeMods;
private ScreenFooter footer;
private FreeModSelectOverlay freeModSelectOverlay = null!;
private FooterButtonFreeMods footerButtonFreeMods = null!;
private ScreenFooter footer = null!;
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
[BackgroundDependencyLoader]
@ -49,8 +47,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddToggleStep("toggle visibility", visible =>
{
if (freeModSelectOverlay != null)
freeModSelectOverlay.State.Value = visible ? Visibility.Visible : Visibility.Hidden;
freeModSelectOverlay.State.Value = visible ? Visibility.Visible : Visibility.Hidden;
});
}

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using Moq;
using NUnit.Framework;
@ -20,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneGameplayChatDisplay : OsuManualInputManagerTestScene
{
private GameplayChatDisplay chatDisplay;
private GameplayChatDisplay chatDisplay = null!;
[Cached(typeof(ILocalUserPlayInfo))]
private ILocalUserPlayInfo localUserInfo;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Linq;
using NUnit.Framework;
@ -70,13 +68,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
RunGameplay();
IBeatmapInfo firstBeatmap = null;
AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.ServerAPIRoom?.Playlist[0].Beatmap);
IBeatmapInfo firstBeatmap = null!;
AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.ServerAPIRoom!.Playlist[0].Beatmap);
selectNewItem(() => OtherBeatmap);
AddUntilStep("first playlist item hasn't changed", () => MultiplayerClient.ServerAPIRoom?.Playlist[0].Beatmap == firstBeatmap);
AddUntilStep("second playlist item changed", () => MultiplayerClient.ClientAPIRoom?.Playlist[1].Beatmap != firstBeatmap);
AddUntilStep("first playlist item hasn't changed", () => MultiplayerClient.ServerAPIRoom!.Playlist[0].Beatmap == firstBeatmap);
AddUntilStep("second playlist item changed", () => MultiplayerClient.ClientAPIRoom!.Playlist[1].Beatmap != firstBeatmap);
}
[Test]
@ -103,7 +101,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for song select", () => CurrentSubScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded);
BeatmapInfo otherBeatmap = null;
BeatmapInfo otherBeatmap = null!;
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap()));
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
@ -23,7 +21,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
private RoomsContainer container;
private RoomsContainer container = null!;
public override void SetUpSteps()
{
@ -65,7 +63,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("select first room", () => container.Rooms.First().TriggerClick());
AddAssert("first spotlight selected", () => checkRoomSelected(RoomManager.Rooms.First(r => r.Category == RoomCategory.Spotlight)));
AddStep("remove last room", () => RoomManager.RemoveRoom(RoomManager.Rooms.MinBy(r => r.RoomID)));
AddStep("remove last room", () => RoomManager.RemoveRoom(RoomManager.Rooms.MinBy(r => r.RoomID)!));
AddAssert("first spotlight still selected", () => checkRoomSelected(RoomManager.Rooms.First(r => r.Category == RoomCategory.Spotlight)));
AddStep("remove spotlight room", () => RoomManager.RemoveRoom(RoomManager.Rooms.Single(r => r.Category == RoomCategory.Spotlight)));
@ -157,7 +155,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo));
// Todo: What even is this case...?
AddStep("set empty filter criteria", () => container.Filter.Value = null);
AddStep("set empty filter criteria", () => container.Filter.Value = new FilterCriteria());
AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5);
AddStep("filter osu! rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo });
@ -195,9 +193,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add rooms", () => RoomManager.AddRooms(3, withPassword: true));
}
private bool checkRoomSelected(Room room) => SelectedRoom.Value == room;
private bool checkRoomSelected(Room? room) => SelectedRoom.Value == room;
private Room getRoomInFlow(int index) =>
private Room? getRoomInFlow(int index) =>
(container.ChildrenOfType<FillFlowContainer<DrawableLoungeRoom>>().First().FlowingChildren.ElementAt(index) as DrawableRoom)?.Room;
}
}

View File

@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createNewItem()
{
SelectedRoom.Value.Playlist = SelectedRoom.Value.Playlist.Append(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
SelectedRoom.Value!.Playlist = SelectedRoom.Value.Playlist.Append(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
ID = SelectedRoom.Value.Playlist.Count,
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@ -18,8 +16,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene
{
private Dictionary<int, ManualClock> clocks;
private MultiSpectatorLeaderboard leaderboard;
private Dictionary<int, ManualClock> clocks = null!;
private MultiSpectatorLeaderboard? leaderboard;
[SetUpSteps]
public override void SetUpSteps()
@ -55,13 +53,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
}, Add);
});
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
AddUntilStep("wait for load", () => leaderboard!.IsLoaded);
AddUntilStep("wait for user population", () => leaderboard.ChildrenOfType<GameplayLeaderboardScore>().Count() == 2);
AddStep("add clock sources", () =>
{
foreach ((int userId, var clock) in clocks)
leaderboard.AddClock(userId, clock);
leaderboard!.AddClock(userId, clock);
});
}

View File

@ -455,7 +455,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
applyToBeatmap?.Invoke(Beatmap.Value);
LoadScreen(spectatorScreen = new MultiSpectatorScreen(SelectedRoom.Value, playingUsers.ToArray()));
LoadScreen(spectatorScreen = new MultiSpectatorScreen(SelectedRoom.Value!, playingUsers.ToArray()));
});
AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectatorScreen.AllPlayersLoaded));

View File

@ -37,10 +37,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestPerUserMods()
{
AddStep("first user has no mods", () => Assert.That(((TestLeaderboard)Leaderboard).UserMods[0], Is.Empty));
AddStep("first user has no mods", () => Assert.That(((TestLeaderboard)Leaderboard!).UserMods[0], Is.Empty));
AddStep("last user has NF mod", () =>
{
Assert.That(((TestLeaderboard)Leaderboard).UserMods[TOTAL_USERS - 1], Has.One.Items);
Assert.That(((TestLeaderboard)Leaderboard!).UserMods[TOTAL_USERS - 1], Has.One.Items);
Assert.That(((TestLeaderboard)Leaderboard).UserMods[TOTAL_USERS - 1].Single(), Is.TypeOf<OsuModNoFail>());
});
}

View File

@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
LoadComponentAsync(new MatchScoreDisplay
{
Team1Score = { BindTarget = Leaderboard.TeamScores[0] },
Team1Score = { BindTarget = Leaderboard!.TeamScores[0] },
Team2Score = { BindTarget = Leaderboard.TeamScores[1] }
}, Add);

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
@ -22,10 +20,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
private LoungeSubScreen loungeScreen;
private Room lastJoinedRoom;
private string lastJoinedPassword;
private LoungeSubScreen loungeScreen = null!;
private Room? lastJoinedRoom;
private string? lastJoinedPassword;
public override void SetUpSteps()
{
@ -87,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestJoinRoomWithIncorrectPasswordViaButton()
{
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover? passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
@ -97,14 +94,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType<OsuButton>().First().TriggerClick());
AddAssert("room not joined", () => loungeScreen.IsCurrentScreen());
AddUntilStep("password prompt still visible", () => passwordEntryPopover.State.Value == Visibility.Visible);
AddUntilStep("password prompt still visible", () => passwordEntryPopover!.State.Value == Visibility.Visible);
AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox);
}
[Test]
public void TestJoinRoomWithIncorrectPasswordViaEnter()
{
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover? passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
@ -114,14 +111,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press enter", () => InputManager.Key(Key.Enter));
AddAssert("room not joined", () => loungeScreen.IsCurrentScreen());
AddUntilStep("password prompt still visible", () => passwordEntryPopover.State.Value == Visibility.Visible);
AddUntilStep("password prompt still visible", () => passwordEntryPopover!.State.Value == Visibility.Visible);
AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox);
}
[Test]
public void TestJoinRoomWithCorrectPassword()
{
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover? passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
@ -137,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestJoinRoomWithPasswordViaKeyboardOnly()
{
DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null;
DrawableLoungeRoom.PasswordEntryPopover? passwordEntryPopover = null;
AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true));
AddStep("select room", () => InputManager.Key(Key.Down));
@ -150,7 +147,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("room join password correct", () => lastJoinedPassword == "password");
}
private void onRoomJoined(Room room, string password)
private void onRoomJoined(Room room, string? password)
{
lastJoinedRoom = room;
lastJoinedPassword = password;

View File

@ -1,12 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
@ -35,17 +32,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerMatchSongSelect : MultiplayerTestScene
{
private BeatmapManager manager;
private RulesetStore rulesets;
private BeatmapManager manager = null!;
private RulesetStore rulesets = null!;
private IList<BeatmapInfo> beatmaps => importedBeatmapSet?.PerformRead(s => s.Beatmaps) ?? new List<BeatmapInfo>();
private IList<BeatmapInfo> beatmaps => importedBeatmapSet.PerformRead(s => s.Beatmaps);
private TestMultiplayerMatchSongSelect songSelect;
private Live<BeatmapSetInfo> importedBeatmapSet;
private TestMultiplayerMatchSongSelect songSelect = null!;
private Live<BeatmapSetInfo> importedBeatmapSet = null!;
[Resolved]
private OsuConfigManager configManager { get; set; }
private OsuConfigManager configManager { get; set; } = null!;
[BackgroundDependencyLoader]
private void load(GameHost host, AudioManager audio)
@ -57,7 +53,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
Dependencies.Cache(detachedBeatmapStore = new DetachedBeatmapStore());
Dependencies.Cache(Realm);
importedBeatmapSet = manager.Import(TestResources.CreateTestBeatmapSetInfo(8, rulesets.AvailableRulesets.ToArray()));
importedBeatmapSet = manager.Import(TestResources.CreateTestBeatmapSetInfo(8, rulesets.AvailableRulesets.ToArray()))!;
Add(detachedBeatmapStore);
}
@ -71,7 +67,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
SelectedMods.SetDefault();
});
AddStep("create song select", () => LoadScreen(songSelect = new TestMultiplayerMatchSongSelect(SelectedRoom.Value)));
AddStep("create song select", () => LoadScreen(songSelect = new TestMultiplayerMatchSongSelect(SelectedRoom.Value!)));
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && songSelect.BeatmapSetsLoaded);
}
@ -88,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestBeatmapConfirmed()
{
BeatmapInfo selectedBeatmap = null;
BeatmapInfo selectedBeatmap = null!;
setUp();
@ -117,8 +113,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
setUp();
AddStep("change ruleset", () => Ruleset.Value = new OsuRuleset().RulesetInfo);
AddStep($"select {allowedMod.ReadableName()} as allowed", () => songSelect.FreeMods.Value = new[] { (Mod)Activator.CreateInstance(allowedMod) });
AddStep($"select {requiredMod.ReadableName()} as required", () => songSelect.Mods.Value = new[] { (Mod)Activator.CreateInstance(requiredMod) });
AddStep($"select {allowedMod.ReadableName()} as allowed", () => songSelect.FreeMods.Value = new[] { (Mod)Activator.CreateInstance(allowedMod)! });
AddStep($"select {requiredMod.ReadableName()} as required", () => songSelect.Mods.Value = new[] { (Mod)Activator.CreateInstance(requiredMod)! });
AddAssert("freemods empty", () => songSelect.FreeMods.Value.Count == 0);
@ -141,7 +137,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create song select", () =>
{
SelectedRoom.Value.Playlist.Single().RulesetID = 2;
SelectedRoom.Value!.Playlist.Single().RulesetID = 2;
songSelect = new TestMultiplayerMatchSongSelect(SelectedRoom.Value, SelectedRoom.Value.Playlist.Single());
songSelect.OnLoadComplete += _ => Ruleset.Value = new TaikoRuleset().RulesetInfo;
LoadScreen(songSelect);
@ -171,7 +167,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public new BeatmapCarousel Carousel => base.Carousel;
public TestMultiplayerMatchSongSelect(Room room, [CanBeNull] PlaylistItem itemToEdit = null)
public TestMultiplayerMatchSongSelect(Room room, PlaylistItem? itemToEdit = null)
: base(room, itemToEdit)
{
}

View File

@ -1,10 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using JetBrains.Annotations;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
@ -42,10 +39,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerMatchSubScreen : MultiplayerTestScene
{
private MultiplayerMatchSubScreen screen;
private BeatmapManager beatmaps;
private BeatmapSetInfo importedSet;
private MultiplayerMatchSubScreen screen = null!;
private BeatmapManager beatmaps = null!;
private BeatmapSetInfo importedSet = null!;
public TestSceneMultiplayerMatchSubScreen()
: base(false)
@ -70,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("load match", () =>
{
SelectedRoom.Value = new Room { Name = "Test Room" };
LoadScreen(screen = new TestMultiplayerMatchSubScreen(SelectedRoom.Value));
LoadScreen(screen = new TestMultiplayerMatchSubScreen(SelectedRoom.Value!));
});
AddUntilStep("wait for load", () => screen.IsCurrentScreen());
@ -81,7 +77,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -100,7 +96,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new TaikoRuleset().RulesetInfo).BeatmapInfo)
{
@ -125,7 +121,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set playlist", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -142,7 +138,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set playlist", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo)
{
@ -173,7 +169,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item with allowed mod", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -202,7 +198,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item with allowed mod", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -226,7 +222,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item with no allowed mods", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -249,7 +245,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add two playlist items", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo)
{
@ -285,7 +281,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
@ -320,8 +316,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
private partial class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen
{
[Resolved(canBeNull: true)]
[CanBeNull]
private IDialogOverlay dialogOverlay { get; set; }
private IDialogOverlay? dialogOverlay { get; set; }
public TestMultiplayerMatchSubScreen(Room room)
: base(room)

View File

@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create list", () =>
{
Child = list = new MultiplayerPlaylist(SelectedRoom.Value)
Child = list = new MultiplayerPlaylist(SelectedRoom.Value!)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create playlist", () =>
{
Child = playlist = new MultiplayerQueueList(SelectedRoom.Value)
Child = playlist = new MultiplayerQueueList(SelectedRoom.Value!)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using NUnit.Framework;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
@ -16,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestDisplayResults()
{
MultiplayerResultsScreen screen = null;
MultiplayerResultsScreen screen = null!;
AddStep("show results screen", () =>
{

View File

@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create button", () =>
{
PlaylistItem item = SelectedRoom.Value.Playlist.First();
PlaylistItem item = SelectedRoom.Value!.Playlist.First();
AvailabilityTracker.SelectedItem.Value = item;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
@ -16,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerSpectatorPlayerGrid : OsuManualInputManagerTestScene
{
private PlayerGrid grid;
private PlayerGrid grid = null!;
[SetUp]
public void Setup() => Schedule(() =>

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Bindables;
@ -32,7 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[TestCase(1048576, 1048576)]
public void TestDisplayTeamResults(int team1Score, int team2Score)
{
MultiplayerResultsScreen screen = null;
MultiplayerResultsScreen screen = null!;
AddStep("show results screen", () =>
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
@ -28,18 +26,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestScenePlaylistsRoomSettingsPlaylist : OnlinePlayTestScene
{
private TestPlaylist playlist;
private TestPlaylist playlist = null!;
[Test]
public void TestItemRemovedOnDeletion()
{
PlaylistItem selectedItem = null;
PlaylistItem selectedItem = null!;
createPlaylist();
moveToItem(0);
AddStep("click", () => InputManager.Click(MouseButton.Left));
AddStep("retrieve selection", () => selectedItem = playlist.SelectedItem.Value);
AddStep("retrieve selection", () => selectedItem = playlist.SelectedItem.Value!);
moveToDeleteButton(0);
AddStep("click delete button", () => InputManager.Click(MouseButton.Left));
@ -122,7 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.MoveMouseTo(item.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistRemoveButton>().ElementAt(0), offset);
});
private void createPlaylist(Action<TestPlaylist> setupPlaylist = null)
private void createPlaylist(Action<TestPlaylist>? setupPlaylist = null)
{
AddStep("create playlist", () =>
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Linq;
using NUnit.Framework;
@ -27,9 +25,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestScenePlaylistsSongSelect : OnlinePlayTestScene
{
private BeatmapManager manager;
private TestPlaylistsSongSelect songSelect;
private BeatmapManager manager = null!;
private TestPlaylistsSongSelect songSelect = null!;
[BackgroundDependencyLoader]
private void load(GameHost host, AudioManager audio)
@ -60,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
SelectedMods.Value = Array.Empty<Mod>();
});
AddStep("create song select", () => LoadScreen(songSelect = new TestPlaylistsSongSelect(SelectedRoom.Value)));
AddStep("create song select", () => LoadScreen(songSelect = new TestPlaylistsSongSelect(SelectedRoom.Value!)));
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && songSelect.BeatmapSetsLoaded);
}
@ -68,14 +65,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void TestItemAddedIfEmptyOnStart()
{
AddStep("finalise selection", () => songSelect.FinaliseSelection());
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value!.Playlist.Count == 1);
}
[Test]
public void TestItemAddedWhenCreateNewItemClicked()
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value!.Playlist.Count == 1);
}
[Test]
@ -83,7 +80,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddStep("finalise selection", () => songSelect.FinaliseSelection());
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value!.Playlist.Count == 1);
}
[Test]
@ -91,7 +88,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddAssert("playlist has 2 items", () => SelectedRoom.Value.Playlist.Count == 2);
AddAssert("playlist has 2 items", () => SelectedRoom.Value!.Playlist.Count == 2);
}
[Test]
@ -99,10 +96,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddStep("rearrange", () => SelectedRoom.Value.Playlist = SelectedRoom.Value.Playlist.Skip(1).Append(SelectedRoom.Value.Playlist[0]).ToArray());
AddStep("rearrange", () => SelectedRoom.Value!.Playlist = SelectedRoom.Value!.Playlist.Skip(1).Append(SelectedRoom.Value!.Playlist[0]).ToArray());
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem!());
AddAssert("new item has id 2", () => SelectedRoom.Value.Playlist.Last().ID == 2);
AddAssert("new item has id 2", () => SelectedRoom.Value!.Playlist.Last().ID == 2);
}
/// <summary>
@ -118,13 +115,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("item 1 has rate 1.5", () =>
{
var mod = (OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
var mod = (OsuModDoubleTime)SelectedRoom.Value!.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
return Precision.AlmostEquals(1.5, mod.SpeedChange.Value);
});
AddAssert("item 2 has rate 2", () =>
{
var mod = (OsuModDoubleTime)SelectedRoom.Value.Playlist.Last().RequiredMods[0].ToMod(new OsuRuleset());
var mod = (OsuModDoubleTime)SelectedRoom.Value!.Playlist.Last().RequiredMods[0].ToMod(new OsuRuleset());
return Precision.AlmostEquals(2, mod.SpeedChange.Value);
});
}
@ -135,7 +132,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestGlobalModInstancesNotRetained()
{
OsuModDoubleTime mod = null;
OsuModDoubleTime mod = null!;
AddStep("set dt mod and store", () =>
{
@ -150,7 +147,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change stored mod rate", () => mod.SpeedChange.Value = 2);
AddAssert("item has rate 1.5", () =>
{
var m = (OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
var m = (OsuModDoubleTime)SelectedRoom.Value!.Playlist.First().RequiredMods[0].ToMod(new OsuRuleset());
return Precision.AlmostEquals(1.5, m.SpeedChange.Value);
});
}

View File

@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set playlist", () =>
{
SelectedRoom.Value.Playlist =
SelectedRoom.Value!.Playlist =
[
new PlaylistItem(new BeatmapInfo { StarRating = min }),
new PlaylistItem(new BeatmapInfo { StarRating = max }),

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Bindables;
@ -21,7 +19,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
private TestLoungeSubScreen loungeScreen;
private TestLoungeSubScreen loungeScreen = null!;
public override void SetUpSteps()
{
@ -97,7 +95,7 @@ namespace osu.Game.Tests.Visual.Playlists
private partial class TestLoungeSubScreen : PlaylistsLoungeSubScreen
{
public new Bindable<Room> SelectedRoom => base.SelectedRoom;
public new Bindable<Room?> SelectedRoom => base.SelectedRoom;
}
}
}

View File

@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
SelectedRoom.Value = new Room();
Child = settings = new TestRoomSettings(SelectedRoom.Value)
Child = settings = new TestRoomSettings(SelectedRoom.Value!)
{
RelativeSizeAxes = Axes.Both,
State = { Value = Visibility.Visible }
@ -45,19 +45,19 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("clear name and beatmap", () =>
{
SelectedRoom.Value.Name = "";
SelectedRoom.Value.Playlist = [];
SelectedRoom.Value!.Name = "";
SelectedRoom.Value!.Playlist = [];
});
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
AddStep("set name", () => SelectedRoom.Value.Name = "Room name");
AddStep("set name", () => SelectedRoom.Value!.Name = "Room name");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
AddStep("set beatmap", () => SelectedRoom.Value.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)]);
AddStep("set beatmap", () => SelectedRoom.Value!.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)]);
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
AddStep("clear name", () => SelectedRoom.Value.Name = "");
AddStep("clear name", () => SelectedRoom.Value!.Name = "");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
}
@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
settings.NameField.Current.Value = expected_name;
settings.DurationField.Current.Value = expectedDuration;
SelectedRoom.Value.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
SelectedRoom.Value!.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
RoomManager.CreateRequested = r =>
{
@ -98,8 +98,8 @@ namespace osu.Game.Tests.Visual.Playlists
{
var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo;
SelectedRoom.Value.Name = "Test Room";
SelectedRoom.Value.Playlist = [new PlaylistItem(beatmap)];
SelectedRoom.Value!.Name = "Test Room";
SelectedRoom.Value!.Playlist = [new PlaylistItem(beatmap)];
errorMessage = $"{not_found_prefix} {beatmap.OnlineID}";
@ -107,13 +107,13 @@ namespace osu.Game.Tests.Visual.Playlists
});
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
AddAssert("playlist item valid", () => SelectedRoom.Value.Playlist[0].Valid.Value);
AddAssert("playlist item valid", () => SelectedRoom.Value!.Playlist[0].Valid.Value);
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
AddAssert("error displayed", () => settings.ErrorText.IsPresent);
AddAssert("error has custom text", () => settings.ErrorText.Text != errorMessage);
AddAssert("playlist item marked invalid", () => !SelectedRoom.Value.Playlist[0].Valid.Value);
AddAssert("playlist item marked invalid", () => !SelectedRoom.Value!.Playlist[0].Valid.Value);
}
[Test]
@ -125,8 +125,8 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("setup", () =>
{
SelectedRoom.Value.Name = "Test Room";
SelectedRoom.Value.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
SelectedRoom.Value!.Name = "Test Room";
SelectedRoom.Value!.Playlist = [new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)];
RoomManager.CreateRequested = _ => failText;
});

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("create component", () =>
{
Child = new ParticipantsDisplay(SelectedRoom.Value, Direction.Horizontal)
Child = new ParticipantsDisplay(SelectedRoom.Value!, Direction.Horizontal)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("create component", () =>
{
Child = new ParticipantsDisplay(SelectedRoom.Value, Direction.Vertical)
Child = new ParticipantsDisplay(SelectedRoom.Value!, Direction.Vertical)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

View File

@ -1,13 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
@ -34,14 +31,14 @@ namespace osu.Game.Tests.Visual.Playlists
private const int scores_per_result = 10;
private const int real_user_position = 200;
private TestResultsScreen resultsScreen;
private TestResultsScreen resultsScreen = null!;
private int lowestScoreId; // Score ID of the lowest score in the list.
private int highestScoreId; // Score ID of the highest score in the list.
private bool requestComplete;
private int totalCount;
private ScoreInfo userScore;
private ScoreInfo userScore = null!;
[SetUpSteps]
public override void SetUpSteps()
@ -205,7 +202,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddAssert("placeholder shown", () => this.ChildrenOfType<MessagePlaceholder>().Count(), () => Is.EqualTo(1));
}
private void createResults(Func<ScoreInfo> getScore = null)
private void createResults(Func<ScoreInfo>? getScore = null)
{
AddStep("load results", () =>
{
@ -229,7 +226,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddWaitStep("wait for display", 5);
}
private void bindHandler(bool delayed = false, ScoreInfo userScore = null, bool failRequests = false, bool noScores = false) => ((DummyAPIAccess)API).HandleRequest = request =>
private void bindHandler(bool delayed = false, ScoreInfo? userScore = null, bool failRequests = false, bool noScores = false) => ((DummyAPIAccess)API).HandleRequest = request =>
{
// pre-check for requests we should be handling (as they are scheduled below).
switch (request)
@ -286,7 +283,7 @@ namespace osu.Game.Tests.Visual.Playlists
req.TriggerFailure(new WebException("Failed."));
}
private MultiplayerScore createUserResponse([NotNull] ScoreInfo userScore)
private MultiplayerScore createUserResponse(ScoreInfo userScore)
{
var multiplayerUserScore = new MultiplayerScore
{
@ -420,7 +417,7 @@ namespace osu.Game.Tests.Visual.Playlists
public new LoadingSpinner RightSpinner => base.RightSpinner;
public new ScorePanelList ScorePanelList => base.ScorePanelList;
public TestResultsScreen([CanBeNull] ScoreInfo score, int roomId, PlaylistItem playlistItem)
public TestResultsScreen(ScoreInfo? score, int roomId, PlaylistItem playlistItem)
: base(score, roomId, playlistItem)
{
AllowRetry = true;

View File

@ -51,7 +51,7 @@ namespace osu.Game.Tests.Visual.Playlists
importBeatmap();
AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value)));
AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value!)));
AddUntilStep("wait for load", () => match.IsCurrentScreen());
}
@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.Playlists
];
});
AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]);
AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value!.Playlist[0]);
}
[Test]
@ -199,7 +199,7 @@ namespace osu.Game.Tests.Visual.Playlists
private void setupAndCreateRoom(Action<Room> room)
{
AddStep("setup room", () => room(SelectedRoom.Value));
AddStep("setup room", () => room(SelectedRoom.Value!));
AddStep("click create button", () =>
{
@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.Playlists
private partial class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen
{
public new Bindable<PlaylistItem> SelectedItem => base.SelectedItem;
public new Bindable<PlaylistItem?> SelectedItem => base.SelectedItem;
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;

View File

@ -18,7 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
public IBindable<bool> InitialRoomsReceived => initialRoomsReceived;
private readonly Bindable<bool> initialRoomsReceived = new Bindable<bool>();
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>();
public readonly Bindable<FilterCriteria?> Filter = new Bindable<FilterCriteria?>();
[BackgroundDependencyLoader]
private void load()

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Linq;
using osu.Framework.Bindables;
@ -26,22 +24,22 @@ namespace osu.Game.Screens.OnlinePlay
/// The currently-selected item. Selection is visually represented with a border.
/// May be updated by clicking playlist items if <see cref="AllowSelection"/> is <c>true</c>.
/// </summary>
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
public readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
/// <summary>
/// Invoked when an item is requested to be deleted.
/// </summary>
public Action<PlaylistItem> RequestDeletion;
public Action<PlaylistItem>? RequestDeletion;
/// <summary>
/// Invoked when an item requests its results to be shown.
/// </summary>
public Action<PlaylistItem> RequestResults;
public Action<PlaylistItem>? RequestResults;
/// <summary>
/// Invoked when an item requests to be edited.
/// </summary>
public Action<PlaylistItem> RequestEdit;
public Action<PlaylistItem>? RequestEdit;
private bool allowReordering;
@ -235,7 +233,7 @@ namespace osu.Game.Screens.OnlinePlay
{
var visibleItems = ListContainer.AsEnumerable().Where(r => r.IsPresent);
PlaylistItem item;
PlaylistItem? item;
if (SelectedItem.Value == null)
item = visibleItems.FirstOrDefault()?.Model;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
@ -54,23 +52,23 @@ namespace osu.Game.Screens.OnlinePlay
/// <summary>
/// Invoked when this item requests to be deleted.
/// </summary>
public Action<PlaylistItem> RequestDeletion;
public Action<PlaylistItem>? RequestDeletion;
/// <summary>
/// Invoked when this item requests its results to be shown.
/// </summary>
public Action<PlaylistItem> RequestResults;
public Action<PlaylistItem>? RequestResults;
/// <summary>
/// Invoked when this item requests to be edited.
/// </summary>
public Action<PlaylistItem> RequestEdit;
public Action<PlaylistItem>? RequestEdit;
/// <summary>
/// The currently-selected item, used to show a border around this item.
/// May be updated by this item if <see cref="AllowSelection"/> is <c>true</c>.
/// </summary>
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
public readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
public readonly PlaylistItem Item;
@ -79,48 +77,48 @@ namespace osu.Game.Screens.OnlinePlay
private readonly DelayedLoadWrapper onScreenLoader = new DelayedLoadWrapper(Empty) { RelativeSizeAxes = Axes.Both };
private readonly IBindable<bool> valid = new Bindable<bool>();
private IBeatmapInfo beatmap;
private IRulesetInfo ruleset;
private IBeatmapInfo? beatmap;
private IRulesetInfo? ruleset;
private Mod[] requiredMods = Array.Empty<Mod>();
private Container borderContainer;
private FillFlowContainer difficultyIconContainer;
private LinkFlowContainer beatmapText;
private LinkFlowContainer authorText;
private ExplicitContentBeatmapBadge explicitContent;
private ModDisplay modDisplay;
private FillFlowContainer buttonsFlow;
private UpdateableAvatar ownerAvatar;
private Drawable showResultsButton;
private Drawable editButton;
private Drawable removeButton;
private PanelBackground panelBackground;
private FillFlowContainer mainFillFlow;
private BeatmapCardThumbnail thumbnail;
private Container? borderContainer;
private FillFlowContainer? difficultyIconContainer;
private LinkFlowContainer? beatmapText;
private LinkFlowContainer? authorText;
private ExplicitContentBeatmapBadge? explicitContent;
private ModDisplay? modDisplay;
private FillFlowContainer? buttonsFlow;
private UpdateableAvatar? ownerAvatar;
private Drawable? showResultsButton;
private Drawable? editButton;
private Drawable? removeButton;
private PanelBackground? panelBackground;
private FillFlowContainer? mainFillFlow;
private BeatmapCardThumbnail? thumbnail;
[Resolved]
private RealmAccess realm { get; set; }
private RealmAccess realm { get; set; } = null!;
[Resolved]
private RulesetStore rulesets { get; set; }
private RulesetStore rulesets { get; set; } = null!;
[Resolved]
private BeatmapManager beatmaps { get; set; }
private BeatmapManager beatmaps { get; set; } = null!;
[Resolved]
private OsuColour colours { get; set; }
private OsuColour colours { get; set; } = null!;
[Resolved]
private UserLookupCache userLookupCache { get; set; }
private UserLookupCache userLookupCache { get; set; } = null!;
[Resolved]
private BeatmapLookupCache beatmapLookupCache { get; set; }
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
[Resolved(CanBeNull = true)]
private BeatmapSetOverlay beatmapOverlay { get; set; }
private BeatmapSetOverlay? beatmapOverlay { get; set; }
[Resolved(CanBeNull = true)]
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
private ManageCollectionsDialog? manageCollectionsDialog { get; set; }
public DrawableRoomPlaylistItem(PlaylistItem item)
: base(item)
@ -136,7 +134,8 @@ namespace osu.Game.Screens.OnlinePlay
[BackgroundDependencyLoader]
private void load()
{
borderContainer.BorderColour = colours.Yellow;
if (borderContainer != null)
borderContainer.BorderColour = colours.Yellow;
ruleset = rulesets.GetRuleset(Item.RulesetID);
var rulesetInstance = ruleset?.CreateInstance();
@ -163,7 +162,8 @@ namespace osu.Game.Screens.OnlinePlay
return;
}
borderContainer.BorderThickness = IsSelectedItem ? border_thickness : 0;
if (borderContainer != null)
borderContainer.BorderThickness = IsSelectedItem ? border_thickness : 0;
}, true);
valid.BindValueChanged(_ => Scheduler.AddOnce(refresh));
@ -177,7 +177,11 @@ namespace osu.Game.Screens.OnlinePlay
if (showItemOwner)
{
var foundUser = await userLookupCache.GetUserAsync(Item.OwnerID).ConfigureAwait(false);
Schedule(() => ownerAvatar.User = foundUser);
Schedule(() =>
{
if (ownerAvatar != null)
ownerAvatar.User = foundUser;
});
}
beatmap = await beatmapLookupCache.GetBeatmapAsync(Item.Beatmap.OnlineID).ConfigureAwait(false);
@ -278,69 +282,89 @@ namespace osu.Game.Screens.OnlinePlay
private void refresh()
{
if (!valid.Value)
if (borderContainer != null)
{
borderContainer.BorderThickness = border_thickness;
borderContainer.BorderColour = colours.Red;
}
if (beatmap != null)
{
difficultyIconContainer.Children = new Drawable[]
if (!valid.Value)
{
thumbnail = new BeatmapCardThumbnail(beatmap.BeatmapSet!, (IBeatmapSetOnlineInfo)beatmap.BeatmapSet!)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Width = 60,
Masking = true,
CornerRadius = 10,
RelativeSizeAxes = Axes.Y,
Dimmed = { Value = IsHovered }
},
new DifficultyIcon(beatmap, ruleset, requiredMods)
{
Size = new Vector2(24),
TooltipType = DifficultyIconTooltipType.Extended,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
};
borderContainer.BorderThickness = border_thickness;
borderContainer.BorderColour = colours.Red;
}
}
else
difficultyIconContainer.Clear();
panelBackground.Beatmap.Value = beatmap;
beatmapText.Clear();
if (beatmap != null)
if (difficultyIconContainer != null)
{
beatmapText.AddLink(beatmap.GetDisplayTitleRomanisable(includeCreator: false),
LinkAction.OpenBeatmap,
beatmap.OnlineID.ToString(),
null,
text =>
if (beatmap != null)
{
difficultyIconContainer.Children = new Drawable[]
{
text.Truncate = true;
});
thumbnail = new BeatmapCardThumbnail(beatmap.BeatmapSet!, (IBeatmapSetOnlineInfo)beatmap.BeatmapSet!)
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Width = 60,
Masking = true,
CornerRadius = 10,
RelativeSizeAxes = Axes.Y,
Dimmed = { Value = IsHovered }
},
new DifficultyIcon(beatmap, ruleset, requiredMods)
{
Size = new Vector2(24),
TooltipType = DifficultyIconTooltipType.Extended,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
};
}
else
difficultyIconContainer.Clear();
}
authorText.Clear();
if (panelBackground != null)
panelBackground.Beatmap.Value = beatmap;
if (!string.IsNullOrEmpty(beatmap?.Metadata.Author.Username))
if (beatmapText != null)
{
authorText.AddText("mapped by ");
authorText.AddUserLink(beatmap.Metadata.Author);
beatmapText.Clear();
if (beatmap != null)
{
beatmapText.AddLink(beatmap.GetDisplayTitleRomanisable(includeCreator: false),
LinkAction.OpenBeatmap,
beatmap.OnlineID.ToString(),
null,
text =>
{
text.Truncate = true;
});
}
}
bool hasExplicitContent = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
explicitContent.Alpha = hasExplicitContent ? 1 : 0;
if (authorText != null)
{
authorText.Clear();
modDisplay.Current.Value = requiredMods.ToArray();
if (!string.IsNullOrEmpty(beatmap?.Metadata.Author.Username))
{
authorText.AddText("mapped by ");
authorText.AddUserLink(beatmap.Metadata.Author);
}
}
buttonsFlow.Clear();
buttonsFlow.ChildrenEnumerable = createButtons();
if (explicitContent != null)
{
bool hasExplicitContent = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
explicitContent.Alpha = hasExplicitContent ? 1 : 0;
}
if (modDisplay != null)
modDisplay.Current.Value = requiredMods.ToArray();
if (buttonsFlow != null)
{
buttonsFlow.Clear();
buttonsFlow.ChildrenEnumerable = createButtons();
}
difficultyIconContainer.FadeInFromZero(500, Easing.OutQuint);
mainFillFlow.FadeInFromZero(500, Easing.OutQuint);
@ -601,7 +625,7 @@ namespace osu.Game.Screens.OnlinePlay
private readonly IBeatmapInfo beatmap;
[Resolved]
private BeatmapManager beatmapManager { get; set; }
private BeatmapManager beatmapManager { get; set; } = null!;
// required for download tracking, as this button hides itself. can probably be removed with a bit of consideration.
public override bool IsPresent => true;
@ -656,7 +680,7 @@ namespace osu.Game.Screens.OnlinePlay
// For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap
private partial class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222)
{
public readonly Bindable<IBeatmapInfo> Beatmap = new Bindable<IBeatmapInfo>();
public readonly Bindable<IBeatmapInfo?> Beatmap = new Bindable<IBeatmapInfo?>();
public PanelBackground()
{

View File

@ -1,18 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Game.Rulesets;
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
public class FilterCriteria
{
public string SearchString;
public string SearchString = string.Empty;
public RoomStatusFilter Status;
public string Category;
public RulesetInfo Ruleset;
public string Category = string.Empty;
public RulesetInfo? Ruleset;
public RoomPermissionsFilter Permissions;
}
}

View File

@ -1,13 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
@ -54,42 +51,42 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
AutoSizeAxes = Axes.Both
};
protected ListingPollingComponent ListingPollingComponent { get; private set; }
protected ListingPollingComponent ListingPollingComponent { get; private set; } = null!;
protected readonly Bindable<Room> SelectedRoom = new Bindable<Room>();
protected readonly Bindable<Room?> SelectedRoom = new Bindable<Room?>();
[Resolved]
private MusicController music { get; set; }
private MusicController music { get; set; } = null!;
[Resolved(CanBeNull = true)]
private OngoingOperationTracker ongoingOperationTracker { get; set; }
private OngoingOperationTracker? ongoingOperationTracker { get; set; }
[Resolved]
private IBindable<RulesetInfo> ruleset { get; set; }
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
[Resolved]
private IAPIProvider api { get; set; }
private IAPIProvider api { get; set; } = null!;
[CanBeNull]
private IDisposable joiningRoomOperation { get; set; }
[CanBeNull]
private LeasedBindable<Room> selectionLease;
[Resolved(CanBeNull = true)]
private IdleTracker? idleTracker { get; set; }
[Resolved]
protected OsuConfigManager Config { get; private set; }
protected OsuConfigManager Config { get; private set; } = null!;
private readonly Bindable<FilterCriteria> filter = new Bindable<FilterCriteria>(new FilterCriteria());
private IDisposable? joiningRoomOperation { get; set; }
private LeasedBindable<Room?>? selectionLease;
private readonly Bindable<FilterCriteria?> filter = new Bindable<FilterCriteria?>();
private readonly IBindable<bool> operationInProgress = new Bindable<bool>();
private readonly IBindable<bool> isIdle = new BindableBool();
private PopoverContainer popoverContainer;
private LoadingLayer loadingLayer;
private RoomsContainer roomsContainer;
private SearchTextBox searchTextBox;
private Dropdown<RoomStatusFilter> statusDropdown;
private PopoverContainer popoverContainer = null!;
private LoadingLayer loadingLayer = null!;
private RoomsContainer roomsContainer = null!;
private SearchTextBox searchTextBox = null!;
private Dropdown<RoomStatusFilter> statusDropdown = null!;
[BackgroundDependencyLoader(true)]
private void load([CanBeNull] IdleTracker idleTracker)
private void load()
{
const float controls_area_height = 25f;
@ -208,7 +205,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
public void UpdateFilter() => Scheduler.AddOnce(updateFilter);
private ScheduledDelegate scheduledFilterUpdate;
private ScheduledDelegate? scheduledFilterUpdate;
private void updateFilterDebounced()
{
@ -262,7 +259,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
if (SelectedRoom.Value?.RoomID == null)
SelectedRoom.Value = new Room();
music?.EnsurePlayingSomething();
music.EnsurePlayingSomething();
onReturning();
}
@ -299,7 +296,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
popoverContainer.HidePopover();
}
public virtual void Join(Room room, string password, Action<Room> onSuccess = null, Action<string> onFailure = null) => Schedule(() =>
public virtual void Join(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onFailure = null) => Schedule(() =>
{
if (joiningRoomOperation != null)
return;
@ -364,7 +361,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
/// Push a room as a new subscreen.
/// </summary>
/// <param name="room">An optional template to use when creating the room.</param>
public void Open(Room room = null) => Schedule(() =>
public void Open(Room? room = null) => Schedule(() =>
{
// Handles the case where a room is clicked 3 times in quick succession
if (!this.IsCurrentScreen())

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
@ -17,7 +15,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
{
private readonly APIUserScoreAggregate score;
public override ScoreInfo TooltipContent => null; // match aggregate scores can't show statistics that the custom tooltip displays.
public override ScoreInfo? TooltipContent => null; // match aggregate scores can't show statistics that the custom tooltip displays.
public MatchLeaderboardScore(APIUserScoreAggregate score, int? rank, bool isOnlineScope = true)
: base(score.CreateScoreInfo(), rank, isOnlineScope)

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@ -26,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
protected override TabItem<MatchType> CreateTabItem(MatchType value) => new GameTypePickerItem(value);
protected override Dropdown<MatchType> CreateDropdown() => null;
protected override Dropdown<MatchType>? CreateDropdown() => null;
public MatchTypePicker()
{
@ -41,7 +39,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
{
private const float transition_duration = 200;
private readonly CircularContainer hover, selection;
private readonly CircularContainer hover;
private readonly CircularContainer selection;
public GameTypePickerItem(MatchType value)
: base(value)
@ -84,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
};
}
private Sample selectSample;
private Sample selectSample = null!;
[BackgroundDependencyLoader]
private void load(OsuColour colours, AudioManager audio)

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
@ -22,7 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
public partial class RoomAvailabilityPicker : DisableableTabControl<RoomAvailability>
{
protected override TabItem<RoomAvailability> CreateTabItem(RoomAvailability value) => new RoomAvailabilityPickerItem(value);
protected override Dropdown<RoomAvailability> CreateDropdown() => null;
protected override Dropdown<RoomAvailability>? CreateDropdown() => null;
public RoomAvailabilityPicker()
{

View File

@ -16,7 +16,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
{
public partial class RoomModSelectOverlay : UserModSelectOverlay
{
public Bindable<PlaylistItem> SelectedItem { get; } = new Bindable<PlaylistItem>();
public Bindable<PlaylistItem?> SelectedItem { get; } = new Bindable<PlaylistItem?>();
[Resolved]
private RulesetStore rulesets { get; set; } = null!;

View File

@ -1,14 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@ -37,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
[Cached(typeof(IPreviewTrackOwner))]
public abstract partial class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner
{
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
public readonly Bindable<PlaylistItem?> SelectedItem = new Bindable<PlaylistItem?>();
public override bool? ApplyModTrackAdjustments => true;
@ -52,9 +49,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
/// A container that provides controls for selection of user mods.
/// This will be shown/hidden automatically when applicable.
/// </summary>
protected Drawable UserModsSection;
protected Drawable? UserModsSection;
private Sample sampleStart;
private Sample? sampleStart;
/// <summary>
/// Any mods applied by/to the local user.
@ -62,28 +59,28 @@ namespace osu.Game.Screens.OnlinePlay.Match
protected readonly Bindable<IReadOnlyList<Mod>> UserMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
[Resolved(CanBeNull = true)]
private IOverlayManager overlayManager { get; set; }
private IOverlayManager? overlayManager { get; set; }
[Resolved]
private MusicController music { get; set; }
private MusicController music { get; set; } = null!;
[Resolved]
private BeatmapManager beatmapManager { get; set; }
private BeatmapManager beatmapManager { get; set; } = null!;
[Resolved]
protected RulesetStore Rulesets { get; private set; }
protected RulesetStore Rulesets { get; private set; } = null!;
[Resolved]
private IAPIProvider api { get; set; } = null!;
[Resolved(canBeNull: true)]
protected OnlinePlayScreen ParentScreen { get; private set; }
protected OnlinePlayScreen? ParentScreen { get; private set; }
[Resolved]
private PreviewTrackManager previewTrackManager { get; set; } = null!;
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
private IDialogOverlay? dialogOverlay { get; set; }
[Cached]
private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
@ -93,13 +90,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
public readonly Room Room;
private readonly bool allowEdit;
internal ModSelectOverlay UserModsSelectOverlay { get; private set; }
internal ModSelectOverlay UserModsSelectOverlay { get; private set; } = null!;
[CanBeNull]
private IDisposable userModsSelectOverlayRegistration;
private RoomSettingsOverlay settingsOverlay;
private Drawable mainContent;
private IDisposable? userModsSelectOverlayRegistration;
private RoomSettingsOverlay settingsOverlay = null!;
private Drawable mainContent = null!;
/// <summary>
/// Creates a new <see cref="RoomSubScreen"/>.
@ -265,7 +260,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
updateSetupState();
}
private void onRoomPropertyChanged(object sender, PropertyChangedEventArgs e)
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Room.RoomID))
updateSetupState();
@ -388,6 +383,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
protected void StartPlay()
{
if (SelectedItem.Value == null)
return;
// User may be at song select or otherwise when the host starts gameplay.
// Ensure that they first return to this screen, else global bindables (beatmap etc.) may be in a bad state.
if (!this.IsCurrentScreen())
@ -401,29 +399,28 @@ namespace osu.Game.Screens.OnlinePlay.Match
sampleStart?.Play();
// fallback is to allow this class to operate when there is no parent OnlineScreen (testing purposes).
var targetScreen = (Screen)ParentScreen ?? this;
var targetScreen = (Screen?)ParentScreen ?? this;
targetScreen.Push(CreateGameplayScreen());
targetScreen.Push(CreateGameplayScreen(SelectedItem.Value));
}
/// <summary>
/// Creates the gameplay screen to be entered.
/// </summary>
/// <param name="selectedItem">The playlist item about to be played.</param>
/// <returns>The screen to enter.</returns>
protected abstract Screen CreateGameplayScreen();
protected abstract Screen CreateGameplayScreen(PlaylistItem selectedItem);
private void selectedItemChanged()
{
updateWorkingBeatmap();
var selected = SelectedItem.Value;
if (selected == null)
if (SelectedItem.Value is not PlaylistItem selected)
return;
var rulesetInstance = Rulesets.GetRuleset(SelectedItem.Value.RulesetID)?.CreateInstance();
var rulesetInstance = Rulesets.GetRuleset(selected.RulesetID)?.CreateInstance();
Debug.Assert(rulesetInstance != null);
var allowedMods = SelectedItem.Value.AllowedMods.Select(m => m.ToMod(rulesetInstance));
var allowedMods = selected.AllowedMods.Select(m => m.ToMod(rulesetInstance));
// Remove any user mods that are no longer allowed.
UserMods.Value = UserMods.Value.Where(m => allowedMods.Any(a => m.GetType() == a.GetType())).ToList();
@ -494,7 +491,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
cancelTrackLooping();
}
private void applyLoopingToTrack(ValueChangedEvent<WorkingBeatmap> _ = null)
private void applyLoopingToTrack(ValueChangedEvent<WorkingBeatmap>? _ = null)
{
if (!this.IsCurrentScreen())
return;
@ -503,8 +500,8 @@ namespace osu.Game.Screens.OnlinePlay.Match
if (track != null)
{
Beatmap.Value.PrepareTrackForPreview(true);
music?.EnsurePlayingSomething();
Beatmap.Value!.PrepareTrackForPreview(true);
music.EnsurePlayingSomething();
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Input.Bindings;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Online.Multiplayer;
@ -12,14 +10,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
public partial class CreateMultiplayerMatchButton : CreateRoomButton
{
private IBindable<bool> isConnected;
private IBindable<bool> operationInProgress;
private IBindable<bool> isConnected = null!;
private IBindable<bool> operationInProgress = null!;
[Resolved]
private MultiplayerClient multiplayerClient { get; set; }
private MultiplayerClient multiplayerClient { get; set; } = null!;
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; }
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
[BackgroundDependencyLoader]
private void load()

View File

@ -1,9 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -20,8 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public partial class GameplayChatDisplay : MatchChatDisplay, IKeyBindingHandler<GlobalAction>
{
[Resolved(CanBeNull = true)]
[CanBeNull]
private ILocalUserPlayInfo localUserInfo { get; set; }
private ILocalUserPlayInfo? localUserInfo { get; set; }
private readonly IBindable<LocalUserPlayingState> localUserPlaying = new Bindable<LocalUserPlayingState>();

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Linq;
using Humanizer;
@ -33,15 +31,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
TimeSpan.FromMinutes(2)
};
public new Action<TimeSpan> Action;
public Action CancelAction;
public new required Action<TimeSpan> Action;
public required Action CancelAction;
[Resolved]
private MultiplayerClient multiplayerClient { get; set; }
private MultiplayerClient multiplayerClient { get; set; } = null!;
[Resolved]
private OsuColour colours { get; set; }
private OsuColour colours { get; set; } = null!;
private readonly Drawable background;

View File

@ -1,14 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Localisation;
using osu.Framework.Threading;
using osu.Game.Graphics;
@ -20,17 +19,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
public partial class MultiplayerReadyButton : ReadyButton
{
[Resolved]
private MultiplayerClient multiplayerClient { get; set; }
private MultiplayerClient multiplayerClient { get; set; } = null!;
[Resolved]
private OsuColour colours { get; set; }
private OsuColour colours { get; set; } = null!;
[CanBeNull]
private MultiplayerRoom room => multiplayerClient.Room;
private MultiplayerRoom? room => multiplayerClient.Room;
private Sample countdownTickSample;
private Sample countdownWarnSample;
private Sample countdownWarnFinalSample;
private Sample? countdownTickSample;
private Sample? countdownWarnSample;
private Sample? countdownWarnFinalSample;
[BackgroundDependencyLoader]
private void load(AudioManager audio)
@ -48,13 +46,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
onRoomUpdated();
}
private MultiplayerCountdown countdown;
private MultiplayerCountdown? countdown;
private double countdownChangeTime;
private ScheduledDelegate countdownUpdateDelegate;
private ScheduledDelegate? countdownUpdateDelegate;
private void onRoomUpdated() => Scheduler.AddOnce(() =>
{
MultiplayerCountdown newCountdown = room?.ActiveCountdowns.SingleOrDefault(c => c is MatchStartCountdown);
MultiplayerCountdown? newCountdown = room?.ActiveCountdowns.SingleOrDefault(c => c is MatchStartCountdown);
if (newCountdown != countdown)
{
@ -171,6 +169,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
get
{
Debug.Assert(countdown != null);
double timeElapsed = Time.Current - countdownChangeTime;
TimeSpan remaining;
@ -224,7 +224,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
base.Dispose(isDisposing);
if (multiplayerClient != null)
if (multiplayerClient.IsNotNull())
multiplayerClient.RoomUpdated -= onRoomUpdated;
}

View File

@ -58,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
client.ToggleSpectate().ContinueWith(_ => endOperation());
void endOperation() => clickOperation?.Dispose();
void endOperation() => clickOperation.Dispose();
}
[BackgroundDependencyLoader]

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -27,12 +25,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public partial class MultiplayerLoungeSubScreen : LoungeSubScreen
{
[Resolved]
private IAPIProvider api { get; set; }
private IAPIProvider api { get; set; } = null!;
[Resolved]
private MultiplayerClient client { get; set; }
private MultiplayerClient client { get; set; } = null!;
private Dropdown<RoomPermissionsFilter> roomAccessTypeDropdown;
private Dropdown<RoomPermissionsFilter> roomAccessTypeDropdown = null!;
public override void OnResuming(ScreenTransitionEvent e)
{
@ -83,7 +81,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
protected override void OpenNewRoom(Room room)
{
if (client?.IsConnected.Value != true)
if (!client.IsConnected.Value)
{
Logger.Log("Not currently connected to the multiplayer server.", LoggingTarget.Runtime, LogLevel.Important);
return;
@ -95,7 +93,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
private partial class MultiplayerListingPollingComponent : ListingPollingComponent
{
[Resolved]
private MultiplayerClient client { get; set; }
private MultiplayerClient client { get; set; } = null!;
private readonly IBindable<bool> isConnected = new Bindable<bool>();

View File

@ -401,7 +401,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
StartPlay();
}
protected override Screen CreateGameplayScreen()
protected override Screen CreateGameplayScreen(PlaylistItem selectedItem)
{
Debug.Assert(client.LocalUser != null);
Debug.Assert(client.Room != null);
@ -415,7 +415,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return new MultiSpectatorScreen(Room, users.Take(PlayerGrid.MAX_PLAYERS).ToArray());
default:
return new MultiplayerPlayerLoader(() => new MultiplayerPlayer(Room, SelectedItem.Value, users));
return new MultiplayerPlayerLoader(() => new MultiplayerPlayer(Room, selectedItem, users));
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Threading.Tasks;
using osu.Framework.Allocation;
@ -18,9 +16,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public bool GameplayPassed => player?.GameplayState.HasPassed == true;
[Resolved]
private MultiplayerClient multiplayerClient { get; set; }
private MultiplayerClient multiplayerClient { get; set; } = null!;
private Player player;
private Player? player;
public MultiplayerPlayerLoader(Func<Player> createPlayer)
: base(createPlayer)
@ -45,7 +43,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
.ContinueWith(task => failAndBail(task.Exception?.Message ?? "Server error"), TaskContinuationOptions.NotOnRanToCompletion);
}
private void failAndBail(string message = null)
private void failAndBail(string? message = null)
{
if (!string.IsNullOrEmpty(message))
Logger.Log(message, LoggingTarget.Runtime, LogLevel.Important);

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@ -22,7 +20,7 @@ namespace osu.Game.Screens.OnlinePlay
private readonly Bindable<bool> inProgress = new BindableBool();
private LeasedBindable<bool> leasedInProgress;
private LeasedBindable<bool>? leasedInProgress;
public OngoingOperationTracker()
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Diagnostics;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@ -27,16 +25,16 @@ namespace osu.Game.Screens.OnlinePlay
public IScreen CurrentSubScreen => screenStack.CurrentScreen;
public override bool CursorVisible => (screenStack?.CurrentScreen as IOnlinePlaySubScreen)?.CursorVisible ?? true;
public override bool CursorVisible => (screenStack.CurrentScreen as IOnlinePlaySubScreen)?.CursorVisible ?? true;
// this is required due to PlayerLoader eventually being pushed to the main stack
// while leases may be taken out by a subscreen.
public override bool DisallowExternalBeatmapRulesetChanges => true;
protected LoungeSubScreen Lounge { get; private set; }
protected LoungeSubScreen Lounge { get; private set; } = null!;
private OnlinePlayScreenWaveContainer waves;
private ScreenStack screenStack;
private readonly ScreenStack screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both };
private OnlinePlayScreenWaveContainer waves = null!;
[Cached(Type = typeof(IRoomManager))]
protected RoomManager RoomManager { get; private set; }
@ -45,7 +43,7 @@ namespace osu.Game.Screens.OnlinePlay
private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker();
[Resolved]
protected IAPIProvider API { get; private set; }
protected IAPIProvider API { get; private set; } = null!;
protected OnlinePlayScreen()
{
@ -67,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both },
screenStack,
new Header(ScreenTitle, screenStack),
RoomManager,
ongoingOperationTracker,

View File

@ -273,10 +273,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})");
}
protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(Room, SelectedItem.Value)
protected override Screen CreateGameplayScreen(PlaylistItem selectedItem)
{
Exited = () => leaderboard.RefetchScores()
});
return new PlayerLoader(() => new PlaylistsPlayer(Room, selectedItem)
{
Exited = () => leaderboard.RefetchScores()
});
}
protected override void Dispose(bool isDisposing)
{

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using System;
using System.Collections.Generic;
using osu.Game.Online.API.Requests.Responses;
@ -28,10 +26,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
public IReadOnlyList<Room> ServerSideRooms => requestsHandler.ServerSideRooms;
public override void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
public override void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
=> base.CreateRoom(room, r => onSuccess?.Invoke(r), onError);
public override void JoinRoom(Room room, string password = null, Action<Room> onSuccess = null, Action<string> onError = null)
public override void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
=> base.JoinRoom(room, password, r => onSuccess?.Invoke(r), onError);
/// <summary>

View File

@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
/// <summary>
/// The cached <see cref="Room"/>.
/// </summary>
Bindable<Room> SelectedRoom { get; }
Bindable<Room?> SelectedRoom { get; }
/// <summary>
/// The cached <see cref="IRoomManager"/>

View File

@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
/// </summary>
public abstract partial class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies
{
public Bindable<Room> SelectedRoom => OnlinePlayDependencies.SelectedRoom;
public Bindable<Room?> SelectedRoom => OnlinePlayDependencies.SelectedRoom;
public IRoomManager RoomManager => OnlinePlayDependencies.RoomManager;
public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies.OngoingOperationTracker;
public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies.AvailabilityTracker;

View File

@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
/// </summary>
public class OnlinePlayTestSceneDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestSceneDependencies
{
public Bindable<Room> SelectedRoom { get; }
public Bindable<Room?> SelectedRoom { get; }
public IRoomManager RoomManager { get; }
public OngoingOperationTracker OngoingOperationTracker { get; }
public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; }
@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
public OnlinePlayTestSceneDependencies()
{
SelectedRoom = new Bindable<Room>();
SelectedRoom = new Bindable<Room?>();
RequestsHandler = new TestRoomRequestsHandler();
OngoingOperationTracker = new OngoingOperationTracker();
AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();