From d4fc6693b4db3b11ffb5ba0ab5ee4a1fc250bc88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 10 Jun 2025 11:46:34 +0200 Subject: [PATCH] Fix stable scores importing with a `LegacyOnlineID` of 0 Closes https://github.com/ppy/osu/issues/33435. The root cause of the issue is that the user's database contained a whole lot of scores with `LegacyOnlineID` of 0, which would trip up https://github.com/ppy/osu/blob/97e6187f0d7c3dbee896596a623e34627135bf0e/osu.Game/Extensions/ModelExtensions.cs#L128-L129 as that method would thus consider scores that are not the same as the same because of the zero, which later trips up https://github.com/ppy/osu/blob/97e6187f0d7c3dbee896596a623e34627135bf0e/osu.Game/Screens/Ranking/SoloResultsScreen.cs#L79 which ends up inserting `Score` into the list several times, which causes the crash. You might remember that I tried to fix this once before in https://github.com/ppy/osu/pull/24794. What I did not realise, however, is that stable *can still produce replays* that have an online ID of zero in them, because zero *is just `default(long)`*: https://github.com/peppy/osu-stable-reference/blob/7205341bb70000a87fa1bd54e7642772e2af85d7/osu!/GameplayElements/Scoring/Score.cs#L123 https://github.com/peppy/osu-stable-reference/blob/7205341bb70000a87fa1bd54e7642772e2af85d7/osu!/GameplayElements/Scoring/Score.cs#L350 The alternative way of fixing this would be just to change `MatchesOnlineID` to reject zeroes, but I think this is a saner overall direction. --- osu.Game/Database/RealmAccess.cs | 9 ++++++++- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 7142f2b300..49bde7c505 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -98,8 +98,9 @@ namespace osu.Game.Database /// 46 2024-12-26 Change beat snap divisor bindings to match stable directionality ¯\_(ツ)_/¯. /// 47 2025-01-21 Remove right mouse button binding for absolute scroll. Never use mouse buttons (or scroll) for global actions. /// 48 2025-03-19 Clear online status for all qualified beatmaps (some were stuck in a qualified state due to local caching issues). + /// 49 2025-06-10 Reset the LegacyOnlineID to -1 for all scores that have it set to 0 (which is semantically the same) for consistency of handling with OnlineID. /// - private const int schema_version = 48; + private const int schema_version = 49; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. @@ -1255,6 +1256,12 @@ namespace osu.Game.Database foreach (var beatmap in beatmaps) beatmap.ResetOnlineInfo(resetOnlineId: false); break; + + case 49: + foreach (var score in migration.NewRealm.All().Where(s => s.LegacyOnlineID == 0)) + score.LegacyOnlineID = -1; + + break; } Logger.Log($"Migration completed in {stopwatch.ElapsedMilliseconds}ms"); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index a32c05c4eb..cf6819b086 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -110,6 +110,9 @@ namespace osu.Game.Scoring.Legacy else if (version >= 20121008) scoreInfo.LegacyOnlineID = sr.ReadInt32(); + if (scoreInfo.LegacyOnlineID == 0) + scoreInfo.LegacyOnlineID = -1; + byte[] compressedScoreInfo = null; if (version >= 30000001)