-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove CachedModelDependencyContainer
and OnlinePlayComposite
from multiplayer
#30634
Remove CachedModelDependencyContainer
and OnlinePlayComposite
from multiplayer
#30634
Conversation
Most important changes are to `RoomSubScreen` and `PlaylistsRoomSubScreen`, because those are the only two cases that now bind to the event instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Posting partial review, 60/103 files in.
/// <summary> | ||
/// Delay before the background is loaded while on-screen. | ||
/// </summary> | ||
public double BackgroundLoadDelay = 500; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor gripe but I think these feel better as explicit properties. I see fields like this and expect them to be constants.
diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs
index 8ddda485b5..be6ca43f4b 100644
--- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs
+++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs
@@ -19,12 +19,12 @@ public partial class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable<IBe
/// <summary>
/// Delay before the background is loaded while on-screen.
/// </summary>
- public double BackgroundLoadDelay = 500;
+ public double BackgroundLoadDelay { get; set; } = 500;
/// <summary>
/// Delay before the background is unloaded while off-screen.
/// </summary>
- public double BackgroundUnloadDelay = 10000;
+ public double BackgroundUnloadDelay { get; set; } = 10000;
[Resolved]
private BeatmapManager beatmaps { get; set; } = null!;
|
||
throw new AggregateException(exceptionText.ToString()); | ||
} | ||
Room.Playlist[Room.Playlist.IndexOf(Room.Playlist.Single(existing => existing.ID == item.ID))] = item; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still a mouthful to parse. But I guess apart from splitting out variables there's not much to be done.
diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
index 998a34931d..7105a3fc91 100644
--- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
@@ -771,8 +771,16 @@ public Task PlaylistItemChanged(MultiplayerPlaylistItem item)
Debug.Assert(APIRoom != null);
- Room.Playlist[Room.Playlist.IndexOf(Room.Playlist.Single(existing => existing.ID == item.ID))] = item;
- APIRoom.Playlist = APIRoom.Playlist.Select((pi, i) => pi.ID == item.ID ? new PlaylistItem(item) : APIRoom.Playlist[i]).ToArray();
+ var existingItem = Room.Playlist.Single(existing => existing.ID == item.ID);
+ Room.Playlist[Room.Playlist.IndexOf(existingItem)] = item;
+
+ APIRoom.Playlist = APIRoom.Playlist.Select((pi, i) =>
+ {
+ if (pi.ID == item.ID)
+ return new PlaylistItem(item);
+
+ return APIRoom.Playlist[i];
+ }).ToArray();
ItemChanged?.Invoke(item);
RoomUpdated?.Invoke();
Marginally better maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just think of this as temporary? I really don't want to duplicate 10 lines of code across 3 files, and in one case where existingItem
is already a local variable so there's even going to be different syntactical structures to the code...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
private void updateRoomPlaylist() | ||
=> playlist.Items.ReplaceRange(0, playlist.Items.Count, room.Playlist); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is going to require some better handling. It can be pretty slow to do a full reload of this list:
osu.2024-11-15.at.07.33.18.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be fixed by ppy/osu-framework#6425
if (a.User == null) | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not be removed (ie. return true
) if it's unwanted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done my best to preserve existing semantics in this PR to not cause unexpected side-effects. Unless you can prove to me otherwise, this will not be changing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass completed.
@@ -164,7 +164,7 @@ private void load(AudioManager audio) | |||
new DrawableMatchRoom(Room, allowEdit) | |||
{ | |||
OnEdit = () => settingsOverlay.Show(), | |||
SelectedItem = { BindTarget = SelectedItem } | |||
SelectedItem = SelectedItem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really hesitant about this one. Assigning directly to a bindable always feels wrong. Reading back on the previous PR, the rationale seems to be that "this means we won't forget to set it"? I dunno how valid that is. Would keeping the old BindTarget
method still be feasible?
And yes, we use BindableWithCurrent
elsewhere like this. The difference I see is that in all those usages (to my knowledge), the property is named Current
, which signifies that it has the special underlying behaviour.
In addition, we're passing this multiple levels down (see MultiplayerMatchFooter
/ MatchStartControl
as one example). We usually tend to use DI in such a case. Could we create a MultiplayerState
cached class for containing things like this as an alternative? Potentially also containing Room
which seems to be passed everywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is one of the most important parts of this series of PRs...
the rationale seems to be that "this means we won't forget to set it"?
It enforces a contract, in the same way a ctor enforces a contract. BindTarget
/BindTo
and all that work, but it must always be assigned. At compile time it says that if you haven't assigned this you're definitely doing something wrong, so think about what you want to do now.
In previous code this would've been an ambient non-nullable resolved bindable that enforced the same contract at run-time, which imo is very hidden, especially for something that potentially has multiple sources (I've only applied this to SelectedItem
, which is exactly this case).
the property is named
Current
, which signifies that it has the special underlying behaviour.
This is not significance to me because I made no effort to use or reproduce IHasCurrentValue<>
. I only wanted to enforce the contract.
Could we create a
MultiplayerState
cached class for containing things like this as an alternative?
To be honest, if you want that then this series of PRs has no need to exist. Because, the natural follow up is - if we BDL Room
, then we might as well keep every property in Room
also bindable. Most of the complexity of this PR goes away I believe.
It's a different take on things. I can't say whether that would be a bad idea, so I'm going to block this PR as I investigate that path instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed IRL, my proposed direction is likely not where we want to go. I can agree that we should avoid caching "states" to DI, especially when those states are not singleton (smoogi mentioned that if we have states here, there will need to be multiple layers to handle lobby/room).
So let's leave things how they are for now.
updateRoomName(); | ||
updateRoomType(); | ||
updateRoomQueueMode(); | ||
updateRoomPassword(); | ||
updateRoomAutoSkip(); | ||
updateRoomMaxParticipants(); | ||
updateRoomAutoStartDuration(); | ||
updateRoomPlaylist(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a bit painful..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm aware and mentioned as such in #30631.
FWIW I've run tests locally for over an hour
No failures.. promising 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it'll be useful but I gave this a review pass.
Generally I will say I don't have the warmest of feelings towards INotifyPropertyChanged
as an interface from prior WPF exposure to it, and it doesn't feel great to basically use yet another method of "notify changed" given we have bindables which are already intended for this expressly. Another thing is that lists don't mix super well with INotifyPropertyChanged
because you can't raise a collection changed event, and so all consumers, if wanting to be efficient, will have to do their local diffing.
That said, from prior experience with daily challenge, multiplayer did feel a little "too boxed in" abstraction-wise. I'm not 100% sure whether this PR helps much in that respect since it seems to be focused more on pure mechanics of change notifications, but I'm willing to try it in pursuit of new features.
Overall I'm neutral on this change. Willing to let this chain run its paces and see what happens.
private void updateRoomName() | ||
{ | ||
if (roomName != null) | ||
roomName.Text = Room.Name; | ||
} | ||
|
||
private void updateRoomCategory() | ||
{ | ||
if (Room.Category > RoomCategory.Normal) | ||
specialCategoryPill?.Show(); | ||
else | ||
specialCategoryPill?.Hide(); | ||
} | ||
|
||
private void updateRoomType() | ||
{ | ||
if (endDateInfo != null) | ||
endDateInfo.Alpha = Room.Type == MatchType.Playlists ? 1 : 0; | ||
} | ||
|
||
private void updateRoomHasPassword() | ||
{ | ||
if (passwordIcon != null) | ||
passwordIcon.Alpha = Room.HasPassword ? 1 : 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to comment above - I probably would have merged these into one method, from experience. I'm talking about every case where these groups of small updateX()
methods have materialised; in my experience the efficiency tradeoff has rarely been worth the mental overhead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected these PRs to be reviewed part by part and not in the final thing. I won't do the NRT changes next time and keep it to one PR, my bad.
In each prior PR I wrote a little explanation of what I believe to be the important parts. I mentioned that I'm aware of this separation in #30631, and am also not convinced with it/will clean it up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected these PRs to be reviewed part by part and not in the final thing
I would have done so, but given that seemingly a full review of this diff was done already here, it felt like the wrong thing to review piece-by-piece now...?
Closed all other PRs and linked them in the description here because it seems everyone is reading this PR. Apologies for the size :/ |
My thinking going into In #30592 I mentioned that I'm not fully sold on the current implementation/location but this is a first step. |
Didn't really work to fix these tests due to the sticky nature of the failure. Also I can no longer reproduce locally, so the hope is that these are fixed by ppy#30634.
Prereqs:
RearrangeableListContainer<>
only replace differences osu-framework#6425Please read previous PRs #30633, #30631, #30598, and #30592 for a gradual explanation of the important changes made.