At the core of the problem is that the multiplayer server does not
serialise beatmap covers to clients -- only the beatmap ids. Because of
this, any components that need to display the background should query it
from an online source first (i.e. via `BeatmapLookupCache`).
There is a slightly tricky situation here formed of two parts, which
I'll try to explain below.
`Background.Sprite` is exposed publicly and some inheritors override the
sprite's texture in a similar fashion to the way this changeset does.
While I frankly believe this is unnaceptable from an encapsulation point
of view, I've gone for consistency in this regard.
The other fail case is `UpdateableBeatmapBackgroundSprite`. Contrary to
its name, that object is _not_ a `Sprite` - it is a
`ModelBackedDrawable` that _contains_ a `Sprite`. The logic in this PR
could be extracted into a separate object similar to
`OnlineBeatmapSetCover` (an actual `Sprite`), but even so it would
require `Background` to provide a path for overriding its contained
`Sprite`.
I went through the path above originally with the changes visible in
https://github.com/smoogipoo/osu/tree/fix-mp-backgrounds, but it looks
quite daunting and I feel like there would be a lot of emphasis on the
correct abstraction model for `Background`, of which I'm not entirely
sure of.
Instead of dealing with both of the above, this commit presents a
direct; local resolution to the problem.
Mostly trying to give more space to the queue as we add more vertical
elements to the middle area of multiplayer / playerlists. This whole UI
will likely change – this is just a stop-gap fix.
Regressed in https://github.com/ppy/osu/pull/28399.
To reproduce, enter a playlist that has an item with a rate-changing mod
(rather than create it yourself).
This is happening because `APIRuleset` has `CreateInstance()`
unimplemented:
https://github.com/ppy/osu/blob/b4cefe0cc2fda0ab4b5af6138ee158bd32262f9a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs#L159
and only triggers when the playlist items in question originate from
web.
This is why it is bad to have interface implementations throw outside of
maybe mock implementations for tests. `CreateInstance()` is a scourge
elsewhere in general, we need way less of it in the codebase (because
while convenient, it's also problematic to implement in online contexts,
and also expensive because reflection).