Fixes https://osu.ppy.sh/community/forums/topics/1983327.
The cause of the bug is a bit convoluted, and stems from the fact that
the mod select overlay controls all of the game-global mod instances if
present. `ModSpeedHotkeyHandler` would store the last spotted instance
of a rate adjust mod - which in this case is a problem, because on
deselection of a mod, the mod select overlay resets its settings to
defaults:
a258059d43/osu.Game/Overlays/Mods/ModSelectOverlay.cs (L424-L425)
A way to defend against this is a clone, but this reveals another issue,
in that the existing code was *relying* on the reference to the mod
remaining the same in any other case, to read the latest valid settings
of the mod. This basically only mattered in the edge case wherein Double
Time would swap places with Half Time and vice versa (think [0.95,1.05]
range). Therefore, track mod settings too explicitly to ensure that the
stored clone is as up-to-date as possible.
@peppy noticed recently that attempting to spectate just a few users was
very likely to end up in requests very quickly being rejected with code
429 ("Too Many Requests").
I'm somewhat certain that the reason for that is that a significant
number of players is wont to retry a lot in quick succession. That means
that spectator server is going to note a lot of gameplay start and end
messages in quick succession, too. And as it turns out, every gameplay
start would end up triggering a new beatmap set fetch request:
ccf1acce56/osu.Game/Screens/Spectate/SpectatorScreen.cs (L131-L134)ccf1acce56/osu.Game/Screens/Play/SoloSpectatorScreen.cs (L168-L172)ccf1acce56/osu.Game/Screens/Play/SoloSpectatorScreen.cs (L243-L256)
To attempt to curtail that, use the beatmap cache instead, which should
prevent these unnecessary requests from firing in the first place,
therefore reducing the chance of the client getting throttled.
This technically means that a different endpoint is used to fetch the
data (`GET /beatmaps/?ids[]=` rather than `GET
/beatmapsets/lookup?beatmap_id={id}`), but docs claim that both should
return the same data, and it looks to work fine in practice.
Compare: https://github.com/ppy/osu/pull/24548.
I don't have a reproduction scenario (judging from the stack trace
of the crash it's likely to be nigh-impossible to concoct a reliable
one), but there is some circumstantial evidence that this might help,
namely that that previous fix above worked, and the pathway that's
failing here is similarly async to the one that pull fixed. So I'm just
gonna start with that and hope that it does the job.