Implement replay downloading with ArchiveDownloadModelManager

This commit is contained in:
naoey 2019-06-12 01:31:57 +05:30
parent e8ea0594b4
commit ab0bb8b678
No known key found for this signature in database
GPG Key ID: 670DA9BE3DF7EE60
7 changed files with 103 additions and 6 deletions

View File

@ -0,0 +1,13 @@
using osu.Game.Scoring;
namespace osu.Game.Online.API.Requests
{
public class DownloadReplayRequest : ArchiveDownloadModelRequest<ScoreInfo>
{
public DownloadReplayRequest(ScoreInfo score)
: base(score)
{
}
protected override string Target => $@"scores/{Info.Ruleset.ShortName}/{Info.OnlineScoreID}/download";
}
}

View File

@ -32,12 +32,15 @@ namespace osu.Game.Online.API.Requests.Responses
set => User = value; set => User = value;
} }
[JsonProperty(@"score_id")] [JsonProperty(@"id")]
private long onlineScoreID private long onlineScoreID
{ {
set => OnlineScoreID = value; set => OnlineScoreID = value;
} }
[JsonProperty(@"replay")]
public bool Replay { get; set; }
[JsonProperty(@"created_at")] [JsonProperty(@"created_at")]
private DateTimeOffset date private DateTimeOffset date
{ {

View File

@ -170,7 +170,7 @@ namespace osu.Game
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Host.Storage, API, contextFactory, Host));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap));
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary // this should likely be moved to ArchiveModelManager when another case appers where it is necessary

View File

@ -16,7 +16,7 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Scoring namespace osu.Game.Scoring
{ {
public class ScoreInfo : IHasFiles<ScoreFileInfo>, IHasPrimaryKey, ISoftDelete public class ScoreInfo : IHasFiles<ScoreFileInfo>, IHasPrimaryKey, ISoftDelete, IEquatable<ScoreInfo>
{ {
public int ID { get; set; } public int ID { get; set; }
@ -182,5 +182,7 @@ namespace osu.Game.Scoring
} }
public override string ToString() => $"{User} playing {Beatmap}"; public override string ToString() => $"{User} playing {Beatmap}";
public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID;
} }
} }

View File

@ -11,12 +11,14 @@ using osu.Framework.Platform;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.IO.Archives; using osu.Game.IO.Archives;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring.Legacy; using osu.Game.Scoring.Legacy;
namespace osu.Game.Scoring namespace osu.Game.Scoring
{ {
public class ScoreManager : ArchiveModelManager<ScoreInfo, ScoreFileInfo> public class ScoreManager : ArchiveDownloadModelManager<ScoreInfo, ScoreFileInfo>
{ {
public override string[] HandledExtensions => new[] { ".osr" }; public override string[] HandledExtensions => new[] { ".osr" };
@ -27,8 +29,8 @@ namespace osu.Game.Scoring
private readonly RulesetStore rulesets; private readonly RulesetStore rulesets;
private readonly Func<BeatmapManager> beatmaps; private readonly Func<BeatmapManager> beatmaps;
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null)
: base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) : base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
{ {
this.rulesets = rulesets; this.rulesets = rulesets;
this.beatmaps = beatmaps; this.beatmaps = beatmaps;
@ -60,5 +62,7 @@ namespace osu.Game.Scoring
public IEnumerable<ScoreInfo> QueryScores(Expression<Func<ScoreInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().Where(query); public IEnumerable<ScoreInfo> QueryScores(Expression<Func<ScoreInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().Where(query);
public ScoreInfo Query(Expression<Func<ScoreInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); public ScoreInfo Query(Expression<Func<ScoreInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query);
protected override ArchiveDownloadModelRequest<ScoreInfo> CreateDownloadRequest(ScoreInfo score, object[] options) => new DownloadReplayRequest(score);
} }
} }

View File

@ -0,0 +1,53 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Scoring;
namespace osu.Game.Screens.Play
{
public class ReplayDownloadButton : DownloadTrackingComposite<ScoreInfo, ScoreManager>
{
[Resolved]
private OsuGame game { get; set; }
[Resolved]
private ScoreManager scores { get; set; }
public ReplayDownloadButton(ScoreInfo score)
: base(score)
{
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
AddInternal(new TwoLayerButton
{
BackgroundColour = colours.Yellow,
Icon = FontAwesome.Solid.PlayCircle,
Text = @"Replay",
HoverColour = colours.YellowDark,
Action = onReplay,
});
}
private void onReplay()
{
if (scores.IsAvailableLocally(ModelInfo.Value))
{
game.PresentScore(ModelInfo.Value);
return;
}
scores.Download(ModelInfo.Value);
scores.ItemAdded += (score, _) =>
{
if (score.Equals(ModelInfo.Value))
game.PresentScore(ModelInfo.Value);
};
}
}
}

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Types; using osu.Game.Screens.Ranking.Types;
@ -10,11 +12,31 @@ namespace osu.Game.Screens.Play
{ {
public class SoloResults : Results public class SoloResults : Results
{ {
[Resolved]
ScoreManager scores { get; set; }
public SoloResults(ScoreInfo score) public SoloResults(ScoreInfo score)
: base(score) : base(score)
{ {
} }
[BackgroundDependencyLoader]
private void load()
{
if (scores.IsAvailableLocally(Score) || hasOnlineReplay)
{
AddInternal(new ReplayDownloadButton(Score)
{
Anchor = Framework.Graphics.Anchor.BottomRight,
Origin = Framework.Graphics.Anchor.BottomRight,
Height = 80,
Width = 100,
});
}
}
private bool hasOnlineReplay => Score is APILegacyScoreInfo apiScore && apiScore.OnlineScoreID != null && apiScore.Replay;
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[] protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
{ {
new ScoreOverviewPageInfo(Score, Beatmap.Value), new ScoreOverviewPageInfo(Score, Beatmap.Value),