Closes https://github.com/ppy/osu/issues/26510.
Time for a rant.
Technically, this "broke" with 9e8d07d314,
but it is actually an end result of upstream behaviours that I am
failing to find a better description for than "utterly broken".
Squirrel (the installer we use) has unit tests. Which is great, power
to them. However, the method in which that testing is implemented leads
to epic levels of WTF breakage.
To determine whether Squirrel is being tested right now, it is checking
all currently loaded assemblies, and determining that if any loaded
assembly contains the magic string of "NUNIT" - among others - it must
be being tested right now:
2442721748/src/Squirrel/SimpleSplat/PlatformModeDetector.cs (L17-L32)
If one assumes that there is no conceivable way that an NUnit assembly
*may* be loaded *without* it being a test context, this *may* seem sane.
Foreshadowing.
(Now, to avoid being hypocritical, we also do this, *but* we do this
by checking if the *entry* assembly is an NUnit:
92db55a527/osu.Framework/Development/DebugUtils.cs (L16-L34)
which seems *much* saner, no?)
Now, why did this break with 9e8d07d314
*specifically*, you might wonder?
Well the reason is this line:
3d3f58c252/osu.Desktop/NVAPI.cs (L183)
Yes you are reading this correctly, it's not NVAPI anything itself that
breaks this, it is *a log statement*. To be precise, what the log
statement *does* to provoke this, is calling into framework. That causes
the framework assembly to load, *which* transitively loads the
`nunit.framework` assembly.
(If you ever find yourself wanting to find out this sort of cursed
knowledge - I hope you never need to - you can run something along
the lines of
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 -- .\osu!.exe
then open the resulting trace in PerfView, and then search the
`Microsoft-Windows-DotNETRuntime/AssemblyLoader/Start` log for
the cursed assembly. In this case, the relevant entry said something
along the lines of
HasStack="True"
ThreadID="23,924"
ProcessorNumber="0"
ClrInstanceID="6"
AssemblyName="nunit.framework, Version=3.13.3.0, Culture=neutral, PublicKeyToken=2638cd05610744eb"
AssemblyPath=""
RequestingAssembly="osu.Framework, Version=2024.113.0.0, Culture=neutral, PublicKeyToken=null"
AssemblyLoadContext="Default"
RequestingAssemblyLoadContext="Default"
ActivityID="/#21032/1/26/"
Either that or just comment the log line for kicks. But the above
is *much* faster.)
Now, what *happens* if Squirrel "detects" that it is being "tested"?
Well, it will refuse to close after executing the "hooks" defined via
`SquirrelAwareApp`:
2442721748/src/Squirrel/SquirrelAwareApp.cs (L85-L88)
and it will also refuse to create version shortcuts:
2442721748/src/Squirrel/UpdateManager.Shortcuts.cs (L63-L65)
Sounds familiar, don't it?
There are days on which I tire of computers. Today is one of them.
Up until now, the `UserActivity` class hierarchy contained things like
beatmap info, room info, full replay info, etc. While this was
convenient, it is soon going to be less so, as the data is sent over the
wire to the spectator server so that the user's activity can be
broadcast to other clients.
To counteract this without creating a second separate and slimmed-down
class hierarchy, slim down the `UserActivity` structure to contain the
bare minimum amounts of data such that the structures aren't overly
large and complex to serialise, but also contain enough data that they
can be used by receiving clients directly without having to do beatmap
or score lookups.