diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 7170dc1685..006e2abf4b 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -148,7 +148,11 @@ private void load(FrameworkConfigManager frameworkConfig)
{
this.frameworkConfig = frameworkConfig;
- ScoreManager.ItemAdded += (score, _, silent) => Schedule(() => LoadScore(score, silent));
+ ScoreManager.ItemAdded += (score, _, silent) =>
+ {
+ if (!silent)
+ Schedule(() => PresentScore(score));
+ };
if (!Host.IsPrimaryInstance)
{
@@ -198,71 +202,12 @@ public void OpenUrlExternally(string url)
externalLinkOpener.OpenUrlExternally(url);
}
- private ScheduledDelegate scoreLoad;
-
///
/// Show a beatmap set as an overlay.
///
/// The set to display.
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
- ///
- /// Present a beatmap at song select.
- ///
- /// The beatmap to select.
- public void PresentBeatmap(BeatmapSetInfo beatmap)
- {
- if (menuScreen == null)
- {
- Schedule(() => PresentBeatmap(beatmap));
- return;
- }
-
- CloseAllOverlays(false);
-
- void setBeatmap()
- {
- if (Beatmap.Disabled)
- {
- Schedule(setBeatmap);
- return;
- }
-
- var databasedSet = beatmap.OnlineBeatmapSetID != null ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash);
-
- if (databasedSet != null)
- {
- // Use first beatmap available for current ruleset, else switch ruleset.
- var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First();
-
- ruleset.Value = first.Ruleset;
- Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);
- }
- }
-
- switch (screenStack.CurrentScreen)
- {
- case SongSelect _:
- break;
- default:
- // navigate to song select if we are not already there.
-
- menuScreen.MakeCurrent();
-
- if (Beatmap.Disabled)
- {
- // we may need to wait for a lease to be returned.
- Schedule(() => PresentBeatmap(beatmap));
- return;
- }
-
- menuScreen.LoadToSolo();
- break;
- }
-
- setBeatmap();
- }
-
///
/// Show a user's profile as an overlay.
///
@@ -275,19 +220,46 @@ void setBeatmap()
/// The beatmap to show.
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId);
- protected void LoadScore(ScoreInfo score, bool silent)
+ ///
+ /// Present a beatmap at song select.
+ ///
+ /// The beatmap to select.
+ public void PresentBeatmap(BeatmapSetInfo beatmap)
{
- if (silent)
- return;
+ var databasedSet = beatmap.OnlineBeatmapSetID != null
+ ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID)
+ : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash);
- scoreLoad?.Cancel();
-
- if (menuScreen == null)
+ if (databasedSet == null)
{
- scoreLoad = Schedule(() => LoadScore(score, false));
+ Logger.Log("The requested beatmap could not be loaded.", LoggingTarget.Information);
return;
}
+ if (screenStack.CurrentScreen is PlaySongSelect)
+ // if we're already at song select then we don't need to return to the main menu.
+ setBeatmap();
+ else
+ performFromMainMenu(setBeatmap, $"load {beatmap}");
+
+ void setBeatmap()
+ {
+ menuScreen.LoadToSolo();
+
+ // Use first beatmap available for current ruleset, else switch ruleset.
+ var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First();
+
+ ruleset.Value = first.Ruleset;
+ Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);
+ }
+ }
+
+ ///
+ /// Present a score's replay.
+ ///
+ /// The beatmap to select.
+ public void PresentScore(ScoreInfo score)
+ {
var databasedScore = ScoreManager.GetScore(score);
var databasedScoreInfo = databasedScore.ScoreInfo;
if (databasedScore.Replay == null)
@@ -303,14 +275,35 @@ protected void LoadScore(ScoreInfo score, bool silent)
return;
}
+ performFromMainMenu(() =>
+ {
+ ruleset.Value = databasedScoreInfo.Ruleset;
+
+ Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
+ Beatmap.Value.Mods.Value = databasedScoreInfo.Mods;
+
+ menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore)));
+ }, $"watch {databasedScoreInfo.User.Username} play {databasedScoreInfo.Beatmap}");
+ }
+
+ private ScheduledDelegate performFromMainMenuTask;
+
+ ///
+ /// Perform an action only after returning to the main menu.
+ /// Eagerly tries to exit the current screen until it succeeds.
+ ///
+ /// The action to perform once we are in the correct state.
+ /// The task name to display in a notification (if we can't immediately reach the main menu state).
+ private void performFromMainMenu(Action action, string taskName)
+ {
if ((screenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false)
{
notifications.Post(new SimpleNotification
{
- Text = $"Click here to watch {databasedScoreInfo.User.Username} on {databasedScoreInfo.Beatmap}",
+ Text = $"Click here to {taskName}",
Activated = () =>
{
- loadScore();
+ action();
return true;
}
});
@@ -318,24 +311,20 @@ protected void LoadScore(ScoreInfo score, bool silent)
return;
}
- loadScore();
+ performFromMainMenuTask?.Cancel();
- void loadScore()
+ CloseAllOverlays(false);
+
+ if (menuScreen?.IsCurrentScreen() != true || Beatmap.Disabled)
{
- if (!menuScreen.IsCurrentScreen() || Beatmap.Disabled)
- {
- menuScreen.MakeCurrent();
- this.Delay(500).Schedule(loadScore, out scoreLoad);
- return;
- }
-
- ruleset.Value = databasedScoreInfo.Ruleset;
-
- Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
- Beatmap.Value.Mods.Value = databasedScoreInfo.Mods;
-
- menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore)));
+ // menuScreen may not be initialised or not be current yet; keep trying.
+ menuScreen?.MakeCurrent();
+ performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName));
+ return;
}
+
+ // success!
+ action();
}
protected override void Dispose(bool isDisposing)