Closes https://github.com/ppy/osu/issues/29832.
The underlying reason for the incorrect sample playback was an equality
comparer failure.
Samples are contained in several pools which are managed by the
playfield. In particular, the pools are keyed by `ISampleInfo`
instances. This means that for correct operation, `ISampleInfo` has to
implement `IEquatable<ISampleInfo>` and also provide an appropriately
correct `GetHashCode()` implementation. Different audible samples must
not compare equal to each other when represented by `ISampleInfo`.
As it turns out, `VolumeAwareHitSampleInfo` failed on this, due to not
overriding equality members. Therefore, a `new
HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_NORMAL,
volume: 70)` was allowed to compare equal to a
`VolumeAwareHitSampleInfo` wrapping it, *even though they correspond to
completely different sounds and go through entirely different lookup
path sequences*.
Therefore, to fix, provide more proper equality implementations for
`VolumeAwareHitSampleInfo`.
When testing note that this issue *only occurs immediately after
placing an object*. Saving and re-entering editor makes this issue go
away. I haven't looked too long into why, but the general gist of it is
ordering; it appears that a `normal-hitnormal` pool exists at point
of query of a new object placement, but does not seem to exist when
entering editor afresh. That said I'm not sure that ordering aspect of
this bug matters much if at all, since the two `IHitSampleInfo`s should
never be allowed to alias with each other at all wrt equality.
@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.