- Closes https://github.com/ppy/osu/issues/4287
- Probably closes https://github.com/ppy/osu/issues/25405 (but not
retroactively)
Up until now, whether or not a replay frame is emitted depended solely
on the user's input, i.e. mouse movement or key presses/releases. This,
intersected with the replay playback system which is given allowance to
perform interpolation between replay frames, leads to potential
situations wherein a replay can play inaccurately when a judgement takes
place without user input meaningfully changing. One such case is slider
ends with their 36ms of judgement leniency; see
https://github.com/ppy/osu/issues/25405#issuecomment-2879031106 for
details on that.
To that end, this commit aims to counteract that issue by *forcing* an
important replay frame to be emitted on every new judgement recorded
during gameplay. This will only benefit rulesets wherein judgements can
occur that are not inherently tied to user input changing, which are
going to be osu! as mentioned above, and maybe possibly catch. I don't
foresee this doing anything relevant for taiko or mania.
I also took the freedom to add type checking, as we can't limit the
usage of `Add()` since it's a Container. The exception thrown also
advises of using the suggested `AddTrigger()` instead.
To implement different different sources of input for KeyCounter, it
is now possible to create a Trigger class (to inherit) instead of
inheriting KeyCounter. This eases the creation of more input sources
(like for tests) while allowing to implement different UI variants.
That way, if another variant of the key counter needs to implemented
(for whathever reason), this can be done by only inheriting KeyCounter
and changing how things are arranged visually.
gathering
KPS Calculator now uses DI to retrieve the clocks. Using `HUDOverlay` it
is now cached for `KeysPerSecondCounter`s to resolve it. This also
allows to make an "Attach" flow like `KeyCounter`.