Skip to content

Commit 2d06c2b

Browse files
authored
Merge pull request #36121 from smoogipoo/mp-fix-availability-tracker
Fix potentially incorrect online play beatmap availability
2 parents 1340e18 + 81f0395 commit 2d06c2b

File tree

10 files changed

+42
-10
lines changed

10 files changed

+42
-10
lines changed

osu.Game.Tests/Online/TestSceneMultiplayerBeatmapAvailabilityTracker.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ private void load(GameHost host)
4444
availableBeatmap = importedSet.Beatmaps[0];
4545
unavailableBeatmap = importedSet.Beatmaps[1];
4646

47-
Realm.Write(r => r.Remove(r.Find<BeatmapInfo>(unavailableBeatmap.ID)!));
47+
Realm.Write(r =>
48+
{
49+
BeatmapInfo available = r.Find<BeatmapInfo>(availableBeatmap.ID)!;
50+
available.OnlineMD5Hash = available.MD5Hash;
51+
52+
r.Remove(r.Find<BeatmapInfo>(unavailableBeatmap.ID)!);
53+
});
4854
}
4955

5056
public override void SetUpSteps()

osu.Game.Tests/Online/TestScenePlaylistsBeatmapAvailabilityTracker.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
using osu.Game.Screens.OnlinePlay.Playlists;
2828
using osu.Game.Tests.Resources;
2929
using osu.Game.Tests.Visual;
30+
using Realms;
3031

3132
namespace osu.Game.Tests.Online
3233
{
@@ -229,6 +230,14 @@ public TestBeatmapImporter(TestBeatmapManager testBeatmapManager, Storage storag
229230

230231
return testBeatmapManager.CurrentImport = base.ImportModel(item, archive, parameters, cancellationToken);
231232
}
233+
234+
protected override void PostImport(BeatmapSetInfo model, Realm realm, ImportParameters parameters)
235+
{
236+
foreach (var beatmap in model.Beatmaps)
237+
beatmap.OnlineMD5Hash = beatmap.MD5Hash;
238+
239+
base.PostImport(model, realm, parameters);
240+
}
232241
}
233242
}
234243

osu.Game/Beatmaps/BeatmapManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ public List<BeatmapSetInfo> GetAllUsableBeatmapSets()
328328
.Filter(query, arguments)
329329
.FirstOrDefault()?.Detach());
330330

331+
/// <summary>
332+
/// Perform a lookup query on available <see cref="BeatmapInfo"/>s for a specific online ID.
333+
/// </summary>
334+
/// <returns>A matching local beatmap info if existing and in a valid state.</returns>
335+
public BeatmapInfo? QueryOnlineBeatmapId(int id) => Realm.Run(r =>
336+
r.All<BeatmapInfo>()
337+
.ForOnlineId(id).SingleOrDefault()?.Detach());
338+
331339
/// <summary>
332340
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
333341
/// </summary>

osu.Game/Database/RealmExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// See the LICENCE file in the repository root for full licence text.
33

44
using System;
5+
using System.Linq;
56
using osu.Framework.Logging;
7+
using osu.Game.Beatmaps;
68
using Realms;
79

810
namespace osu.Game.Database
@@ -102,5 +104,13 @@ public static T Write<T>(this Realm realm, Func<Realm, T> function)
102104
/// Quite often we only care about changes at a collection level. This can be used to guard and early-return when no such changes are in a callback.
103105
/// </remarks>
104106
public static bool HasCollectionChanges(this ChangeSet changes) => changes.InsertedIndices.Length > 0 || changes.DeletedIndices.Length > 0 || changes.Moves.Length > 0;
107+
108+
public static IQueryable<BeatmapInfo> NotDeleted(this IQueryable<BeatmapInfo> beatmaps) =>
109+
beatmaps.Filter($@"{nameof(BeatmapInfo.BeatmapSet)}.{nameof(BeatmapSetInfo.DeletePending)} == false");
110+
111+
public static IQueryable<BeatmapInfo> ForOnlineId(this IQueryable<BeatmapInfo> beatmaps, int id) =>
112+
beatmaps
113+
.NotDeleted()
114+
.Filter($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", id);
105115
}
106116
}

osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallenge.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ public static void TrySetDailyChallengeBeatmap(OsuScreen screen, BeatmapManager
489489
if (!screen.IsCurrentScreen())
490490
return;
491491

492-
var beatmap = beatmaps.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", item.Beatmap.OnlineID);
492+
var beatmap = beatmaps.QueryOnlineBeatmapId(item.Beatmap.OnlineID);
493493

494494
screen.Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap); // this will gracefully fall back to dummy beatmap if missing locally.
495495
screen.Ruleset.Value = rulesets.GetRuleset(item.RulesetID);

osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ private void updateGameplayState()
246246

247247
// Update global gameplay state to correspond to the new selection.
248248
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
249-
var localBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", item.BeatmapID);
249+
var localBeatmap = beatmapManager.QueryOnlineBeatmapId(item.BeatmapID);
250250

251251
if (localBeatmap != null)
252252
{

osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ private void onActivePlaylistItemChanged()
510510
{
511511
MultiplayerPlaylistItem item = client.Room.CurrentPlaylistItem;
512512

513-
var newBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", item.BeatmapID);
513+
var newBeatmap = beatmapManager.QueryOnlineBeatmapId(item.BeatmapID);
514514

515515
if (!Beatmap.Value.BeatmapSetInfo.Equals(newBeatmap?.BeatmapSet))
516516
this.MakeCurrent();
@@ -652,7 +652,7 @@ private void updateGameplayState()
652652

653653
// Update global gameplay state to correspond to the new selection.
654654
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
655-
var localBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", gameplayBeatmapId);
655+
var localBeatmap = beatmapManager.QueryOnlineBeatmapId(gameplayBeatmapId);
656656
Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
657657
Ruleset.Value = ruleset;
658658
Mods.Value = client.LocalUser.Mods.Concat(item.RequiredMods).Select(m => m.ToMod(rulesetInstance)).ToArray();

osu.Game/Screens/OnlinePlay/OnlinePlayBeatmapAvailabilityTracker.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using osu.Game.Online;
1818
using osu.Game.Online.API.Requests.Responses;
1919
using osu.Game.Online.Rooms;
20-
using Realms;
2120

2221
namespace osu.Game.Screens.OnlinePlay
2322
{
@@ -154,7 +153,8 @@ void updateAvailability()
154153
}
155154

156155
IQueryable<BeatmapInfo> queryBeatmap() =>
157-
realm.Realm.All<BeatmapInfo>().Filter("OnlineID == $0 && MD5Hash == $1 && BeatmapSet.DeletePending == false", beatmap.OnlineID, beatmap.MD5Hash);
156+
realm.Realm.All<BeatmapInfo>()
157+
.ForOnlineId(beatmap.OnlineID);
158158
}
159159

160160
protected override void Dispose(bool isDisposing)

osu.Game/Screens/OnlinePlay/Playlists/PlaylistItemResultsScreen.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ protected PlaylistItemResultsScreen(ScoreInfo? score, long roomId, PlaylistItem
6262
[BackgroundDependencyLoader]
6363
private void load()
6464
{
65-
var localBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}",
66-
PlaylistItem.Beatmap.OnlineID);
65+
var localBeatmap = beatmapManager.QueryOnlineBeatmapId(PlaylistItem.Beatmap.OnlineID);
6766
itemBeatmap = beatmapManager.GetWorkingBeatmap(localBeatmap);
6867

6968
AddInternal(new Container

osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ private void updateGameplayState()
609609

610610
// Update global gameplay state to correspond to the new selection.
611611
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
612-
var localBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", gameplayBeatmap.OnlineID);
612+
var localBeatmap = beatmapManager.QueryOnlineBeatmapId(gameplayBeatmap.OnlineID);
613613
Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap);
614614
Ruleset.Value = gameplayRuleset;
615615
Mods.Value = UserMods.Value.Concat(item.RequiredMods.Select(m => m.ToMod(rulesetInstance))).ToArray();

0 commit comments

Comments
 (0)