Fell out when attempting
https://github.com/ppy/osu-server-spectator/pull/346.
Functionally, if a true non-`HubException` is produced via an invocation
of a spectator server hub method, this doesn't really do much - the
error will still log as 'unobserved' due to the default handler, it will
still show up on sentry, etc. The only difference is that it'll get
handled via the continuation installed in `FireAndForget()` rather than
the `TaskScheduler.UnobservedTaskException` event.
The only real case where this is relevant is when the server throws
`HubException`s, which will now instead bubble up to a more
human-readable form. Which is relevant to the aforementioned PR because
that one makes any hub method potentially throw a `HubException` if the
client version is too old.
Obviously this does nothing for the existing old clients.
Closes https://github.com/ppy/osu/issues/33465 probably.
This reverts the replay frame de-duplication logic to what it was before
https://github.com/ppy/osu/pull/33148#discussion_r2091549388.
I don't have good reproduction steps. I tried to write a test case for
this that isn't just "press and release a key in the same frame",
thinking that maybe there was some loophole in the osu! touch input
mapper that may produce this situation artificially, but I could not in
many configurations. So I have to assume that this just *can happen*
organically.
When the server requests a disconnect due to a user connecting
via a second device, the client will now log the user out on the first
device and show a notification informing them of the cause of
disconnection.