1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-07 23:15:45 +08:00

Make RoomID non-bindable

Most important changes are to `RoomSubScreen` and `PlaylistsRoomSubScreen`, because those are the only two cases that now bind to the event instead.
This commit is contained in:
Dan Balasescu 2024-11-13 16:28:39 +09:00
parent db025d81ee
commit 99762da7b8
No known key found for this signature in database
35 changed files with 176 additions and 167 deletions

View File

@ -75,7 +75,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
var newRoom = new Room(); var newRoom = new Room();
newRoom.CopyFrom(SelectedRoom.Value); newRoom.CopyFrom(SelectedRoom.Value);
newRoom.RoomID.Value = null; newRoom.RoomID = null;
MultiplayerClient.RoomSetupAction = room => MultiplayerClient.RoomSetupAction = room =>
{ {
room.State = MultiplayerRoomState.Playing; room.State = MultiplayerRoomState.Playing;

View File

@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
{ {
var room = new Room var room = new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Name = { Value = "Daily Challenge: June 4, 2024" }, Name = { Value = "Daily Challenge: June 4, 2024" },
Playlist = Playlist =
{ {
@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
{ {
var room = new Room var room = new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Name = { Value = "Daily Challenge: June 4, 2024" }, Name = { Value = "Daily Challenge: June 4, 2024" },
Playlist = Playlist =
{ {
@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
{ {
var room = new Room var room = new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Name = { Value = "Daily Challenge: June 4, 2024" }, Name = { Value = "Daily Challenge: June 4, 2024" },
Playlist = Playlist =
{ {

View File

@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
{ {
API.Perform(new CreateRoomRequest(room = new Room API.Perform(new CreateRoomRequest(room = new Room
{ {
RoomID = { Value = roomId }, RoomID = roomId,
Name = { Value = "Daily Challenge: June 4, 2024" }, Name = { Value = "Daily Challenge: June 4, 2024" },
Playlist = Playlist =
{ {

View File

@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
return false; return false;
}; };
}); });
AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = { Value = 1 } }, new PlaylistItem(Beatmap.Value.BeatmapInfo)) AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = 1 }, new PlaylistItem(Beatmap.Value.BeatmapInfo))
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.DailyChallenge
return false; return false;
}; };
}); });
AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = { Value = 1 } }, new PlaylistItem(Beatmap.Value.BeatmapInfo)) AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = 1 }, new PlaylistItem(Beatmap.Value.BeatmapInfo))
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Menus
beatmap.OnlineID = 1001; beatmap.OnlineID = 1001;
getRoomRequest.TriggerSuccess(new Room getRoomRequest.TriggerSuccess(new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Name = { Value = "Aug 8, 2024" }, Name = { Value = "Aug 8, 2024" },
Playlist = Playlist =
{ {

View File

@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create leaderboard", () => AddStep("create leaderboard", () =>
{ {
SelectedRoom.Value = new Room { RoomID = { Value = 3 } }; SelectedRoom.Value = new Room { RoomID = 3 };
Child = new MatchLeaderboard Child = new MatchLeaderboard
{ {

View File

@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("create list", () => AddStep("create list", () =>
{ {
SelectedRoom.Value = new Room { RoomID = { Value = 7 } }; SelectedRoom.Value = new Room { RoomID = 7 };
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {

View File

@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.UserInterface
beatmap.OnlineID = 1001; beatmap.OnlineID = 1001;
getRoomRequest.TriggerSuccess(new Room getRoomRequest.TriggerSuccess(new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Playlist = Playlist =
{ {
new PlaylistItem(beatmap) new PlaylistItem(beatmap)
@ -131,7 +131,7 @@ namespace osu.Game.Tests.Visual.UserInterface
beatmap.OnlineID = 1001; beatmap.OnlineID = 1001;
getRoomRequest.TriggerSuccess(new Room getRoomRequest.TriggerSuccess(new Room
{ {
RoomID = { Value = 1234 }, RoomID = 1234,
Playlist = Playlist =
{ {
new PlaylistItem(beatmap) new PlaylistItem(beatmap)

View File

@ -181,10 +181,10 @@ namespace osu.Game.Online.Multiplayer
await joinOrLeaveTaskChain.Add(async () => await joinOrLeaveTaskChain.Add(async () =>
{ {
Debug.Assert(room.RoomID.Value != null); Debug.Assert(room.RoomID != null);
// Join the server-side room. // Join the server-side room.
var joinedRoom = await JoinRoom(room.RoomID.Value.Value, password ?? room.Password.Value).ConfigureAwait(false); var joinedRoom = await JoinRoom(room.RoomID.Value, password ?? room.Password.Value).ConfigureAwait(false);
Debug.Assert(joinedRoom != null); Debug.Assert(joinedRoom != null);
// Populate users. // Populate users.

View File

@ -27,6 +27,6 @@ namespace osu.Game.Online.Rooms
return req; return req;
} }
protected override string Target => $@"rooms/{Room.RoomID.Value}/users/{User!.Id}"; protected override string Target => $@"rooms/{Room.RoomID}/users/{User!.Id}";
} }
} }

View File

@ -23,6 +23,6 @@ namespace osu.Game.Online.Rooms
return req; return req;
} }
protected override string Target => $"rooms/{room.RoomID.Value}/users/{User!.Id}"; protected override string Target => $"rooms/{room.RoomID}/users/{User!.Id}";
} }
} }

View File

@ -21,6 +21,15 @@ namespace osu.Game.Online.Rooms
{ {
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// The online room ID. Will be <c>null</c> while the room has not yet been created.
/// </summary>
public long? RoomID
{
get => roomId;
set => SetField(ref roomId, value);
}
/// <summary> /// <summary>
/// Represents the current item selected within the room. /// Represents the current item selected within the room.
/// </summary> /// </summary>
@ -33,13 +42,12 @@ namespace osu.Game.Online.Rooms
set => SetField(ref currentPlaylistItem, value); set => SetField(ref currentPlaylistItem, value);
} }
[JsonProperty("id")]
private long? roomId;
[JsonProperty("current_playlist_item")] [JsonProperty("current_playlist_item")]
private PlaylistItem? currentPlaylistItem; private PlaylistItem? currentPlaylistItem;
[Cached]
[JsonProperty("id")]
public readonly Bindable<long?> RoomID = new Bindable<long?>();
[Cached] [Cached]
[JsonProperty("name")] [JsonProperty("name")]
public readonly Bindable<string> Name = new Bindable<string>(); public readonly Bindable<string> Name = new Bindable<string>();
@ -196,7 +204,7 @@ namespace osu.Game.Online.Rooms
/// <param name="other">The <see cref="Room"/> to copy values from.</param> /// <param name="other">The <see cref="Room"/> to copy values from.</param>
public void CopyFrom(Room other) public void CopyFrom(Room other)
{ {
RoomID.Value = other.RoomID.Value; RoomID = other.RoomID;
Name.Value = other.Name.Value; Name.Value = other.Name.Value;
Category.Value = other.Category.Value; Category.Value = other.Category.Value;

View File

@ -155,9 +155,9 @@ namespace osu.Game.Screens.Menu
Room = room; Room = room;
cover.OnlineInfo = TooltipContent = room.Playlist.FirstOrDefault()?.Beatmap.BeatmapSet as APIBeatmapSet; cover.OnlineInfo = TooltipContent = room.Playlist.FirstOrDefault()?.Beatmap.BeatmapSet as APIBeatmapSet;
if (room.StartDate.Value != null && room.RoomID.Value != lastDailyChallengeRoomID) if (room.StartDate.Value != null && room.RoomID != lastDailyChallengeRoomID)
{ {
lastDailyChallengeRoomID = room.RoomID.Value; lastDailyChallengeRoomID = room.RoomID;
// new challenge is live, reset intro played static. // new challenge is live, reset intro played static.
statics.SetValue(Static.DailyChallengeIntroPlayed, false); statics.SetValue(Static.DailyChallengeIntroPlayed, false);

View File

@ -1,13 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Development; using osu.Framework.Development;
@ -20,18 +17,17 @@ namespace osu.Game.Screens.OnlinePlay.Components
{ {
public partial class RoomManager : Component, IRoomManager public partial class RoomManager : Component, IRoomManager
{ {
[CanBeNull] public event Action? RoomsUpdated;
public event Action RoomsUpdated;
private readonly BindableList<Room> rooms = new BindableList<Room>(); private readonly BindableList<Room> rooms = new BindableList<Room>();
public IBindableList<Room> Rooms => rooms; public IBindableList<Room> Rooms => rooms;
protected IBindable<Room> JoinedRoom => joinedRoom; protected IBindable<Room?> JoinedRoom => joinedRoom;
private readonly Bindable<Room> joinedRoom = new Bindable<Room>(); private readonly Bindable<Room?> joinedRoom = new Bindable<Room?>();
[Resolved] [Resolved]
private IAPIProvider api { get; set; } private IAPIProvider api { get; set; } = null!;
public RoomManager() public RoomManager()
{ {
@ -44,7 +40,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
PartRoom(); PartRoom();
} }
public virtual void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) public virtual void CreateRoom(Room room, Action<Room>? onSuccess = null, Action<string>? onError = null)
{ {
room.Host.Value = api.LocalUser.Value; room.Host.Value = api.LocalUser.Value;
@ -69,9 +65,9 @@ namespace osu.Game.Screens.OnlinePlay.Components
api.Queue(req); api.Queue(req);
} }
private JoinRoomRequest currentJoinRoomRequest; private JoinRoomRequest? currentJoinRoomRequest;
public virtual void JoinRoom(Room room, string password = null, Action<Room> onSuccess = null, Action<string> onError = null) public virtual void JoinRoom(Room room, string? password = null, Action<Room>? onSuccess = null, Action<string>? onError = null)
{ {
currentJoinRoomRequest?.Cancel(); currentJoinRoomRequest?.Cancel();
currentJoinRoomRequest = new JoinRoomRequest(room, password); currentJoinRoomRequest = new JoinRoomRequest(room, password);
@ -97,7 +93,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{ {
currentJoinRoomRequest?.Cancel(); currentJoinRoomRequest?.Cancel();
if (JoinedRoom.Value == null) if (joinedRoom.Value == null)
return; return;
if (api.State.Value == APIState.Online) if (api.State.Value == APIState.Online)
@ -111,14 +107,14 @@ namespace osu.Game.Screens.OnlinePlay.Components
public void AddOrUpdateRoom(Room room) public void AddOrUpdateRoom(Room room)
{ {
Debug.Assert(ThreadSafety.IsUpdateThread); Debug.Assert(ThreadSafety.IsUpdateThread);
Debug.Assert(room.RoomID.Value != null); Debug.Assert(room.RoomID != null);
if (ignoredRooms.Contains(room.RoomID.Value.Value)) if (ignoredRooms.Contains(room.RoomID.Value))
return; return;
try try
{ {
var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); var existing = rooms.FirstOrDefault(e => e.RoomID == room.RoomID);
if (existing == null) if (existing == null)
rooms.Add(room); rooms.Add(room);
else else
@ -128,7 +124,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{ {
Logger.Error(ex, $"Failed to update room: {room.Name.Value}."); Logger.Error(ex, $"Failed to update room: {room.Name.Value}.");
ignoredRooms.Add(room.RoomID.Value.Value); ignoredRooms.Add(room.RoomID.Value);
rooms.Remove(room); rooms.Remove(room);
} }

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
@ -20,21 +18,21 @@ namespace osu.Game.Screens.OnlinePlay.Components
this.room = room; this.room = room;
} }
private GetRoomRequest lastPollRequest; private GetRoomRequest? lastPollRequest;
protected override Task Poll() protected override Task Poll()
{ {
if (!API.IsLoggedIn) if (!API.IsLoggedIn)
return base.Poll(); return base.Poll();
if (room.RoomID.Value == null) if (room.RoomID == null)
return base.Poll(); return base.Poll();
var tcs = new TaskCompletionSource<bool>(); var tcs = new TaskCompletionSource<bool>();
lastPollRequest?.Cancel(); lastPollRequest?.Cancel();
var req = new GetRoomRequest(room.RoomID.Value.Value); var req = new GetRoomRequest(room.RoomID.Value);
req.Success += result => req.Success += result =>
{ {

View File

@ -353,12 +353,12 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
private void presentScore(long id) private void presentScore(long id)
{ {
if (this.IsCurrentScreen()) if (this.IsCurrentScreen())
this.Push(new PlaylistItemScoreResultsScreen(room.RoomID.Value!.Value, playlistItem, id)); this.Push(new PlaylistItemScoreResultsScreen(room.RoomID!.Value, playlistItem, id));
} }
private void onRoomScoreSet(MultiplayerRoomScoreSetEvent e) private void onRoomScoreSet(MultiplayerRoomScoreSetEvent e)
{ {
if (e.RoomID != room.RoomID.Value || e.PlaylistItemID != playlistItem.ID) if (e.RoomID != room.RoomID || e.PlaylistItemID != playlistItem.ID)
return; return;
userLookupCache.GetUserAsync(e.UserID).ContinueWith(t => userLookupCache.GetUserAsync(e.UserID).ContinueWith(t =>
@ -410,7 +410,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
private void dailyChallengeChanged(ValueChangedEvent<DailyChallengeInfo?> change) private void dailyChallengeChanged(ValueChangedEvent<DailyChallengeInfo?> change)
{ {
if (change.OldValue?.RoomID == room.RoomID.Value && change.NewValue == null && metadataClient.IsConnected.Value) if (change.OldValue?.RoomID == room.RoomID && change.NewValue == null && metadataClient.IsConnected.Value)
{ {
notificationOverlay?.Post(new SimpleNotification { Text = DailyChallengeStrings.ChallengeEndedNotification }); notificationOverlay?.Post(new SimpleNotification { Text = DailyChallengeStrings.ChallengeEndedNotification });
} }
@ -437,7 +437,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
roomManager.JoinRoom(room); roomManager.JoinRoom(room);
startLoopingTrack(this, musicController); startLoopingTrack(this, musicController);
metadataClient.BeginWatchingMultiplayerRoom(room.RoomID.Value!.Value).ContinueWith(t => metadataClient.BeginWatchingMultiplayerRoom(room.RoomID!.Value).ContinueWith(t =>
{ {
if (t.Exception != null) if (t.Exception != null)
{ {
@ -489,7 +489,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
roomManager.PartRoom(); roomManager.PartRoom();
metadataClient.EndWatchingMultiplayerRoom(room.RoomID.Value!.Value).FireAndForget(); metadataClient.EndWatchingMultiplayerRoom(room.RoomID!.Value).FireAndForget();
return base.OnExiting(e); return base.OnExiting(e);
} }

View File

@ -138,7 +138,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
if (request?.CompletionState == APIRequestCompletionState.Waiting) if (request?.CompletionState == APIRequestCompletionState.Waiting)
return; return;
request = new IndexPlaylistScoresRequest(room.RoomID.Value!.Value, playlistItem.ID); request = new IndexPlaylistScoresRequest(room.RoomID!.Value, playlistItem.ID);
request.Success += req => Schedule(() => request.Success += req => Schedule(() =>
{ {

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
@ -11,6 +9,7 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
@ -24,8 +23,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{ {
public partial class RoomsContainer : CompositeDrawable, IKeyBindingHandler<GlobalAction> public partial class RoomsContainer : CompositeDrawable, IKeyBindingHandler<GlobalAction>
{ {
public readonly Bindable<Room> SelectedRoom = new Bindable<Room>(); public readonly Bindable<Room?> SelectedRoom = new Bindable<Room?>();
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>(); public readonly Bindable<FilterCriteria?> Filter = new Bindable<FilterCriteria?>();
public IReadOnlyList<DrawableRoom> Rooms => roomFlow.FlowingChildren.Cast<DrawableRoom>().ToArray(); public IReadOnlyList<DrawableRoom> Rooms => roomFlow.FlowingChildren.Cast<DrawableRoom>().ToArray();
@ -33,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
private readonly FillFlowContainer<DrawableLoungeRoom> roomFlow; private readonly FillFlowContainer<DrawableLoungeRoom> roomFlow;
[Resolved] [Resolved]
private IRoomManager roomManager { get; set; } private IRoomManager roomManager { get; set; } = null!;
// handle deselection // handle deselection
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
@ -67,10 +66,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
rooms.BindTo(roomManager.Rooms); rooms.BindTo(roomManager.Rooms);
Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true); Filter.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true);
} }
private void applyFilterCriteria(FilterCriteria criteria) private void applyFilterCriteria(FilterCriteria? criteria)
{ {
roomFlow.Children.ForEach(r => roomFlow.Children.ForEach(r =>
{ {
@ -113,7 +112,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
} }
} }
private void roomsChanged(object sender, NotifyCollectionChangedEventArgs args) private void roomsChanged(object? sender, NotifyCollectionChangedEventArgs args)
{ {
switch (args.Action) switch (args.Action)
{ {
@ -142,7 +141,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
foreach (var room in rooms) foreach (var room in rooms)
roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = SelectedRoom }); roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = SelectedRoom });
applyFilterCriteria(Filter?.Value); applyFilterCriteria(Filter.Value);
} }
private void removeRooms(IEnumerable<Room> rooms) private void removeRooms(IEnumerable<Room> rooms)
@ -173,7 +172,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
roomFlow.SetLayoutPosition(room, room.Room.Category.Value > RoomCategory.Normal roomFlow.SetLayoutPosition(room, room.Room.Category.Value > RoomCategory.Normal
// Always show spotlight playlists at the top of the listing. // Always show spotlight playlists at the top of the listing.
? float.MinValue ? float.MinValue
: -(room.Room.RoomID.Value ?? 0)); : -(room.Room.RoomID ?? 0));
} }
} }
@ -213,7 +212,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent); var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent);
Room room; Room? room;
if (SelectedRoom.Value == null) if (SelectedRoom.Value == null)
room = visibleRooms.FirstOrDefault()?.Room; room = visibleRooms.FirstOrDefault()?.Room;
@ -236,7 +235,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
if (roomManager != null) if (roomManager.IsNotNull())
roomManager.RoomsUpdated -= updateSorting; roomManager.RoomsUpdated -= updateSorting;
} }
} }

View File

@ -259,7 +259,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
selectionLease.Return(); selectionLease.Return();
selectionLease = null; selectionLease = null;
if (SelectedRoom.Value?.RoomID.Value == null) if (SelectedRoom.Value?.RoomID == null)
SelectedRoom.Value = new Room(); SelectedRoom.Value = new Room();
music?.EnsurePlayingSomething(); music?.EnsurePlayingSomething();
@ -326,19 +326,19 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
/// <param name="room">The room to copy.</param> /// <param name="room">The room to copy.</param>
public void OpenCopy(Room room) public void OpenCopy(Room room)
{ {
Debug.Assert(room.RoomID.Value != null); Debug.Assert(room.RoomID != null);
if (joiningRoomOperation != null) if (joiningRoomOperation != null)
return; return;
joiningRoomOperation = ongoingOperationTracker?.BeginOperation(); joiningRoomOperation = ongoingOperationTracker?.BeginOperation();
var req = new GetRoomRequest(room.RoomID.Value.Value); var req = new GetRoomRequest(room.RoomID.Value);
req.Success += r => req.Success += r =>
{ {
// ID must be unset as we use this as a marker for whether this is a client-side (not-yet-created) room or not. // ID must be unset as we use this as a marker for whether this is a client-side (not-yet-created) room or not.
r.RoomID.Value = null; r.RoomID = null;
// Null out dates because end date is not supported client-side and the settings overlay will populate a duration. // Null out dates because end date is not supported client-side and the settings overlay will populate a duration.
r.EndDate.Value = null; r.EndDate.Value = null;

View File

@ -36,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
private void updateChannel() private void updateChannel()
{ {
if (room.RoomID.Value == null || channelId.Value == 0) if (room.RoomID == null || channelId.Value == 0)
return; return;
Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId.Value, Type = ChannelType.Multiplayer, Name = $"#lazermp_{room.RoomID.Value}" }); Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId.Value, Type = ChannelType.Multiplayer, Name = $"#lazermp_{room.RoomID.Value}" });

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -23,7 +21,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
protected const float TRANSITION_DURATION = 350; protected const float TRANSITION_DURATION = 350;
protected const float FIELD_PADDING = 25; protected const float FIELD_PADDING = 25;
protected OnlinePlayComposite Settings { get; set; } protected OnlinePlayComposite Settings { get; set; } = null!;
protected override bool BlockScrollInput => false; protected override bool BlockScrollInput => false;

View File

@ -5,6 +5,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -29,6 +30,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Screens.OnlinePlay.Match namespace osu.Game.Screens.OnlinePlay.Match
{ {
@ -59,8 +61,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
/// </summary> /// </summary>
protected readonly Bindable<IReadOnlyList<Mod>> UserMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>()); protected readonly Bindable<IReadOnlyList<Mod>> UserMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
protected readonly IBindable<long?> RoomId = new Bindable<long?>();
[Resolved(CanBeNull = true)] [Resolved(CanBeNull = true)]
private IOverlayManager overlayManager { get; set; } private IOverlayManager overlayManager { get; set; }
@ -82,6 +82,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
[Resolved] [Resolved]
private PreviewTrackManager previewTrackManager { get; set; } = null!; private PreviewTrackManager previewTrackManager { get; set; } = null!;
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
[Cached] [Cached]
private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
@ -109,8 +112,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
this.allowEdit = allowEdit; this.allowEdit = allowEdit;
Padding = new MarginPadding { Top = Header.HEIGHT }; Padding = new MarginPadding { Top = Header.HEIGHT };
RoomId.BindTo(room.RoomID);
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -252,9 +253,27 @@ namespace osu.Game.Screens.OnlinePlay.Match
{ {
base.LoadComplete(); base.LoadComplete();
RoomId.BindValueChanged(id => SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem);
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap());
userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(UserModsSelectOverlay);
Room.PropertyChanged += onRoomPropertyChanged;
updateSetupState();
}
private void onRoomPropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (id.NewValue == null) if (e.PropertyName == nameof(Room.RoomID))
updateSetupState();
}
private void updateSetupState()
{
if (Room.RoomID == null)
{ {
// A new room is being created. // A new room is being created.
// The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed.
@ -266,15 +285,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
mainContent.Show(); mainContent.Show();
settingsOverlay.Hide(); settingsOverlay.Hide();
} }
}, true);
SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem);
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap());
userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(UserModsSelectOverlay);
} }
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@ -285,14 +295,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
}; };
} }
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
protected virtual bool IsConnected => api.State.Value == APIState.Online; protected virtual bool IsConnected => api.State.Value == APIState.Online;
public override bool OnBackButton() public override bool OnBackButton()
{ {
if (Room.RoomID.Value == null) if (Room.RoomID == null)
{ {
if (!ensureExitConfirmed()) if (!ensureExitConfirmed())
return true; return true;
@ -365,7 +372,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
if (!IsConnected) if (!IsConnected)
return true; return true;
bool hasUnsavedChanges = Room.RoomID.Value == null && Room.Playlist.Count > 0; bool hasUnsavedChanges = Room.RoomID == null && Room.Playlist.Count > 0;
if (dialogOverlay == null || !hasUnsavedChanges) if (dialogOverlay == null || !hasUnsavedChanges)
return true; return true;
@ -538,6 +545,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
base.Dispose(isDisposing); base.Dispose(isDisposing);
userModsSelectOverlayRegistration?.Dispose(); userModsSelectOverlayRegistration?.Dispose();
Room.PropertyChanged -= onRoomPropertyChanged;
} }
} }
} }

View File

@ -353,7 +353,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true); RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true);
Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true);
MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true); MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true);
RoomID.BindValueChanged(roomId => playlistContainer.Alpha = roomId.NewValue == null ? 1 : 0, true);
Password.BindValueChanged(password => PasswordTextBox.Text = password.NewValue ?? string.Empty, true); Password.BindValueChanged(password => PasswordTextBox.Text = password.NewValue ?? string.Empty, true);
QueueMode.BindValueChanged(mode => QueueModeDropdown.Current.Value = mode.NewValue, true); QueueMode.BindValueChanged(mode => QueueModeDropdown.Current.Value = mode.NewValue, true);
AutoStartDuration.BindValueChanged(duration => startModeDropdown.Current.Value = (StartMode)(int)duration.NewValue.TotalSeconds, true); AutoStartDuration.BindValueChanged(duration => startModeDropdown.Current.Value = (StartMode)(int)duration.NewValue.TotalSeconds, true);
@ -382,6 +381,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
base.Update(); base.Update();
ApplyButton.Enabled.Value = Playlist.Count > 0 && NameField.Text.Length > 0 && !operationInProgress.Value; ApplyButton.Enabled.Value = Playlist.Count > 0 && NameField.Text.Length > 0 && !operationInProgress.Value;
playlistContainer.Alpha = room.RoomID == null ? 1 : 0;
} }
private void apply() private void apply()

View File

@ -54,7 +54,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public MultiplayerMatchSubScreen(Room room) public MultiplayerMatchSubScreen(Room room)
: base(room) : base(room)
{ {
Title = room.RoomID.Value == null ? "New room" : room.Name.Value; Title = room.RoomID == null ? "New room" : room.Name.Value;
Activity.Value = new UserActivity.InLobby(room); Activity.Value = new UserActivity.InLobby(room);
} }

View File

@ -1,14 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -29,17 +28,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
protected override UserActivity InitialActivity => new UserActivity.InMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); protected override UserActivity InitialActivity => new UserActivity.InMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
[Resolved] [Resolved]
private MultiplayerClient client { get; set; } private MultiplayerClient client { get; set; } = null!;
private IBindable<bool> isConnected; private IBindable<bool> isConnected = null!;
private readonly TaskCompletionSource<bool> resultsReady = new TaskCompletionSource<bool>(); private readonly TaskCompletionSource<bool> resultsReady = new TaskCompletionSource<bool>();
private readonly MultiplayerRoomUser[] users; private readonly MultiplayerRoomUser[] users;
private LoadingLayer loadingDisplay; private LoadingLayer loadingDisplay = null!;
private MultiplayerGameplayLeaderboard multiplayerLeaderboard = null!;
private MultiplayerGameplayLeaderboard multiplayerLeaderboard;
/// <summary> /// <summary>
/// Construct a multiplayer player. /// Construct a multiplayer player.
@ -153,7 +150,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
GameplayClockContainer.Reset(); GameplayClockContainer.Reset();
} }
private void failAndBail(string message = null) private void failAndBail(string? message = null)
{ {
if (!string.IsNullOrEmpty(message)) if (!string.IsNullOrEmpty(message))
Logger.Log(message, LoggingTarget.Runtime, LogLevel.Important); Logger.Log(message, LoggingTarget.Runtime, LogLevel.Important);
@ -196,14 +193,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
protected override ResultsScreen CreateResults(ScoreInfo score) protected override ResultsScreen CreateResults(ScoreInfo score)
{ {
Debug.Assert(Room.RoomID.Value != null); Debug.Assert(Room.RoomID != null);
return multiplayerLeaderboard.TeamScores.Count == 2 return multiplayerLeaderboard.TeamScores.Count == 2
? new MultiplayerTeamResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem, multiplayerLeaderboard.TeamScores) ? new MultiplayerTeamResultsScreen(score, Room.RoomID.Value, PlaylistItem, multiplayerLeaderboard.TeamScores)
{ {
ShowUserStatistics = true, ShowUserStatistics = true,
} }
: new MultiplayerResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem) : new MultiplayerResultsScreen(score, Room.RoomID.Value, PlaylistItem)
{ {
ShowUserStatistics = true ShowUserStatistics = true
}; };
@ -213,7 +210,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
if (client != null) if (client.IsNotNull())
{ {
client.GameplayStarted -= onGameplayStarted; client.GameplayStarted -= onGameplayStarted;
client.ResultsReady -= onResultsReady; client.ResultsReady -= onResultsReady;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -18,12 +16,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public partial class MultiplayerRoomManager : RoomManager public partial class MultiplayerRoomManager : RoomManager
{ {
[Resolved] [Resolved]
private MultiplayerClient multiplayerClient { get; set; } private MultiplayerClient multiplayerClient { get; set; } = null!;
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 => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), 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)
{ {
if (!multiplayerClient.IsConnected.Value) if (!multiplayerClient.IsConnected.Value)
{ {
@ -51,9 +49,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
multiplayerClient.LeaveRoom(); multiplayerClient.LeaveRoom();
} }
private void joinMultiplayerRoom(Room room, string password, Action<Room> onSuccess = null, Action<string> onError = null) private void joinMultiplayerRoom(Room room, string? password, Action<Room>? onSuccess = null, Action<string>? onError = null)
{ {
Debug.Assert(room.RoomID.Value != null); Debug.Assert(room.RoomID != null);
multiplayerClient.JoinRoom(room, password).ContinueWith(t => multiplayerClient.JoinRoom(room, password).ContinueWith(t =>
{ {

View File

@ -16,9 +16,6 @@ namespace osu.Game.Screens.OnlinePlay
/// </summary> /// </summary>
public partial class OnlinePlayComposite : CompositeDrawable public partial class OnlinePlayComposite : CompositeDrawable
{ {
[Resolved(typeof(Room))]
protected Bindable<long?> RoomID { get; private set; } = null!;
[Resolved(typeof(Room), nameof(Room.Name))] [Resolved(typeof(Room), nameof(Room.Name))]
protected Bindable<string> RoomName { get; private set; } = null!; protected Bindable<string> RoomName { get; private set; } = null!;

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -21,11 +19,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
public partial class PlaylistsPlayer : RoomSubmittingPlayer public partial class PlaylistsPlayer : RoomSubmittingPlayer
{ {
public Action Exited; public Action? Exited;
protected override UserActivity InitialActivity => new UserActivity.InPlaylistGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); protected override UserActivity InitialActivity => new UserActivity.InPlaylistGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
public PlaylistsPlayer(Room room, PlaylistItem playlistItem, PlayerConfiguration configuration = null) public PlaylistsPlayer(Room room, PlaylistItem playlistItem, PlayerConfiguration? configuration = null)
: base(room, playlistItem, configuration) : base(room, playlistItem, configuration)
{ {
} }
@ -57,8 +55,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
protected override ResultsScreen CreateResults(ScoreInfo score) protected override ResultsScreen CreateResults(ScoreInfo score)
{ {
Debug.Assert(Room.RoomID.Value != null); Debug.Assert(Room.RoomID != null);
return new PlaylistItemUserResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem) return new PlaylistItemUserResultsScreen(score, Room.RoomID.Value, PlaylistItem)
{ {
AllowRetry = true, AllowRetry = true,
ShowUserStatistics = true, ShowUserStatistics = true,

View File

@ -372,7 +372,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private void onPlaylistChanged(object? sender, NotifyCollectionChangedEventArgs e) => private void onPlaylistChanged(object? sender, NotifyCollectionChangedEventArgs e) =>
playlistLength.Text = $"Length: {Playlist.GetTotalDuration(rulesets)}"; playlistLength.Text = $"Length: {Playlist.GetTotalDuration(rulesets)}";
private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0 private bool hasValidSettings => room.RoomID == null && NameField.Text.Length > 0 && Playlist.Count > 0
&& hasValidDuration; && hasValidDuration;
private bool hasValidDuration => DurationField.Current.Value <= TimeSpan.FromDays(14) || localUser.Value.IsSupporter; private bool hasValidDuration => DurationField.Current.Value <= TimeSpan.FromDays(14) || localUser.Value.IsSupporter;

View File

@ -1,11 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -22,6 +20,7 @@ using osu.Game.Screens.Play;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osu.Game.Users; using osu.Game.Users;
using osuTK; using osuTK;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Screens.OnlinePlay.Playlists namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
@ -33,20 +32,22 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private readonly IBindable<bool> isIdle = new BindableBool(); private readonly IBindable<bool> isIdle = new BindableBool();
private MatchLeaderboard leaderboard; [Resolved(CanBeNull = true)]
private SelectionPollingComponent selectionPollingComponent; private IdleTracker? idleTracker { get; set; }
private FillFlowContainer progressSection; private MatchLeaderboard leaderboard = null!;
private SelectionPollingComponent selectionPollingComponent = null!;
private FillFlowContainer progressSection = null!;
public PlaylistsRoomSubScreen(Room room) public PlaylistsRoomSubScreen(Room room)
: base(room, false) // Editing is temporarily not allowed. : base(room, false) // Editing is temporarily not allowed.
{ {
Title = room.RoomID.Value == null ? "New playlist" : room.Name.Value; Title = room.RoomID == null ? "New playlist" : room.Name.Value;
Activity.Value = new UserActivity.InLobby(room); Activity.Value = new UserActivity.InLobby(room);
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader]
private void load([CanBeNull] IdleTracker idleTracker) private void load()
{ {
if (idleTracker != null) if (idleTracker != null)
isIdle.BindTo(idleTracker.IsIdle); isIdle.BindTo(idleTracker.IsIdle);
@ -59,17 +60,26 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
base.LoadComplete(); base.LoadComplete();
isIdle.BindValueChanged(_ => updatePollingRate(), true); isIdle.BindValueChanged(_ => updatePollingRate(), true);
RoomId.BindValueChanged(id => Room.MaxAttempts.BindValueChanged(_ => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true);
Room.PropertyChanged += onRoomPropertyChanged;
updateSetupState();
}
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if (id.NewValue != null) if (e.PropertyName == nameof(Room.RoomID))
updateSetupState();
}
private void updateSetupState()
{
if (Room.RoomID != null)
{ {
// Set the first playlist item. // Set the first playlist item.
// This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()). // This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()).
Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault()); Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault());
} }
}, true);
Room.MaxAttempts.BindValueChanged(_ => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true);
} }
protected override Drawable CreateMainContent() => new Container protected override Drawable CreateMainContent() => new Container
@ -92,7 +102,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
}, },
Content = new[] Content = new[]
{ {
new Drawable[] new Drawable?[]
{ {
// Playlist items column // Playlist items column
new GridContainer new GridContainer
@ -113,8 +123,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
AllowShowingResults = true, AllowShowingResults = true,
RequestResults = item => RequestResults = item =>
{ {
Debug.Assert(RoomId.Value != null); Debug.Assert(Room.RoomID != null);
ParentScreen?.Push(new PlaylistItemUserResultsScreen(null, RoomId.Value.Value, item)); ParentScreen?.Push(new PlaylistItemUserResultsScreen(null, Room.RoomID.Value, item));
} }
} }
}, },
@ -248,5 +258,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
Exited = () => leaderboard.RefetchScores() Exited = () => leaderboard.RefetchScores()
}); });
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
Room.PropertyChanged -= onRoomPropertyChanged;
}
} }
} }

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System.Diagnostics; using System.Diagnostics;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.Online.API; using osu.Game.Online.API;
@ -19,16 +17,16 @@ namespace osu.Game.Screens.Play
protected readonly PlaylistItem PlaylistItem; protected readonly PlaylistItem PlaylistItem;
protected readonly Room Room; protected readonly Room Room;
protected RoomSubmittingPlayer(Room room, PlaylistItem playlistItem, PlayerConfiguration configuration = null) protected RoomSubmittingPlayer(Room room, PlaylistItem playlistItem, PlayerConfiguration? configuration = null)
: base(configuration) : base(configuration)
{ {
Room = room; Room = room;
PlaylistItem = playlistItem; PlaylistItem = playlistItem;
} }
protected override APIRequest<APIScoreToken> CreateTokenRequest() protected override APIRequest<APIScoreToken>? CreateTokenRequest()
{ {
if (!(Room.RoomID.Value is long roomId)) if (Room.RoomID is not long roomId)
return null; return null;
int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID; int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID;
@ -45,8 +43,8 @@ namespace osu.Game.Screens.Play
protected override APIRequest<MultiplayerScore> CreateSubmissionRequest(Score score, long token) protected override APIRequest<MultiplayerScore> CreateSubmissionRequest(Score score, long token)
{ {
Debug.Assert(Room.RoomID.Value != null); Debug.Assert(Room.RoomID != null);
return new SubmitRoomScoreRequest(score.ScoreInfo, token, Room.RoomID.Value.Value, PlaylistItem.ID); return new SubmitRoomScoreRequest(score.ScoreInfo, token, Room.RoomID.Value, PlaylistItem.ID);
} }
} }
} }

View File

@ -214,7 +214,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
roomId = clone(roomId); roomId = clone(roomId);
password = clone(password); password = clone(password);
ServerAPIRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId); ServerAPIRoom = roomManager.ServerSideRooms.Single(r => r.RoomID == roomId);
if (password != ServerAPIRoom.Password.Value) if (password != ServerAPIRoom.Password.Value)
throw new InvalidOperationException("Invalid password."); throw new InvalidOperationException("Invalid password.");

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
@ -17,23 +15,23 @@ namespace osu.Game.Tests.Visual.OnlinePlay
/// </summary> /// </summary>
public partial class TestRoomManager : RoomManager public partial class TestRoomManager : RoomManager
{ {
public Action<Room, string> JoinRoomRequested; public Action<Room, string?>? JoinRoomRequested;
private int currentRoomId; private int currentRoomId;
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)
{ {
JoinRoomRequested?.Invoke(room, password); JoinRoomRequested?.Invoke(room, password);
base.JoinRoom(room, password, onSuccess, onError); base.JoinRoom(room, password, onSuccess, onError);
} }
public void AddRooms(int count, RulesetInfo ruleset = null, bool withPassword = false, bool withSpotlightRooms = false) public void AddRooms(int count, RulesetInfo? ruleset = null, bool withPassword = false, bool withSpotlightRooms = false)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
var room = new Room var room = new Room
{ {
RoomID = { Value = -currentRoomId }, RoomID = -currentRoomId,
Name = { Value = $@"Room {currentRoomId}" }, Name = { Value = $@"Room {currentRoomId}" },
Host = { Value = new APIUser { Username = @"Host" } }, Host = { Value = new APIUser { Username = @"Host" } },
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },

View File

@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
case JoinRoomRequest joinRoomRequest: case JoinRoomRequest joinRoomRequest:
{ {
var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); var room = ServerSideRooms.Single(r => r.RoomID == joinRoomRequest.Room.RoomID);
if (joinRoomRequest.Password != room.Password.Value) if (joinRoomRequest.Password != room.Password.Value)
{ {
@ -162,7 +162,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
return true; return true;
case GetRoomRequest getRoomRequest: case GetRoomRequest getRoomRequest:
getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID == getRoomRequest.RoomId), true));
return true; return true;
case CreateRoomScoreRequest createRoomScoreRequest: case CreateRoomScoreRequest createRoomScoreRequest:
@ -261,7 +261,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
/// <param name="host">The room host.</param> /// <param name="host">The room host.</param>
public void AddServerSideRoom(Room room, APIUser host) public void AddServerSideRoom(Room room, APIUser host)
{ {
room.RoomID.Value ??= currentRoomId++; room.RoomID ??= currentRoomId++;
room.Host.Value = host; room.Host.Value = host;
for (int i = 0; i < room.Playlist.Count; i++) for (int i = 0; i < room.Playlist.Count; i++)

View File

@ -248,7 +248,7 @@ namespace osu.Game.Users
public InLobby(Room room) public InLobby(Room room)
{ {
RoomID = room.RoomID.Value ?? -1; RoomID = room.RoomID ?? -1;
RoomName = room.Name.Value; RoomName = room.Name.Value;
} }