mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 06:42:56 +08:00
Make OnlinePlayBeatmapAvailabilityTracker look up the online beatmap
This commit is contained in:
parent
afcb7a4630
commit
94a974e1c9
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -12,6 +13,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
@ -21,6 +23,8 @@ using osu.Game.Database;
|
|||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
@ -53,6 +57,25 @@ namespace osu.Game.Tests.Online
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
|
((DummyAPIAccess)API).HandleRequest = req =>
|
||||||
|
{
|
||||||
|
switch (req)
|
||||||
|
{
|
||||||
|
case GetBeatmapsRequest beatmapsReq:
|
||||||
|
var beatmap = CreateAPIBeatmap();
|
||||||
|
beatmap.OnlineID = testBeatmapInfo.OnlineID;
|
||||||
|
beatmap.OnlineBeatmapSetID = testBeatmapSet.OnlineID;
|
||||||
|
beatmap.Checksum = testBeatmapInfo.MD5Hash;
|
||||||
|
beatmap.BeatmapSet!.OnlineID = testBeatmapSet.OnlineID;
|
||||||
|
|
||||||
|
beatmapsReq.TriggerSuccess(new GetBeatmapsResponse { Beatmaps = new List<APIBeatmap> { beatmap } });
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
beatmaps.AllowImport = new TaskCompletionSource<bool>();
|
beatmaps.AllowImport = new TaskCompletionSource<bool>();
|
||||||
|
|
||||||
testBeatmapFile = TestResources.GetQuickTestBeatmapForImport();
|
testBeatmapFile = TestResources.GetQuickTestBeatmapForImport();
|
||||||
@ -69,12 +92,30 @@ namespace osu.Game.Tests.Online
|
|||||||
RulesetID = testBeatmapInfo.Ruleset.OnlineID,
|
RulesetID = testBeatmapInfo.Ruleset.OnlineID,
|
||||||
};
|
};
|
||||||
|
|
||||||
Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
recreateChildren();
|
||||||
{
|
|
||||||
SelectedItem = { BindTarget = selectedItem, }
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private void recreateChildren()
|
||||||
|
{
|
||||||
|
var beatmapLookupCache = new BeatmapLookupCache();
|
||||||
|
|
||||||
|
Child = new DependencyProvidingContainer
|
||||||
|
{
|
||||||
|
CachedDependencies = new[]
|
||||||
|
{
|
||||||
|
(typeof(BeatmapLookupCache), (object)beatmapLookupCache)
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
beatmapLookupCache,
|
||||||
|
availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
||||||
|
{
|
||||||
|
SelectedItem = { BindTarget = selectedItem, }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBeatmapDownloadingFlow()
|
public void TestBeatmapDownloadingFlow()
|
||||||
{
|
{
|
||||||
@ -123,10 +164,7 @@ namespace osu.Game.Tests.Online
|
|||||||
});
|
});
|
||||||
addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
|
addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
|
||||||
|
|
||||||
AddStep("recreate tracker", () => Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
|
AddStep("recreate tracker", recreateChildren);
|
||||||
{
|
|
||||||
SelectedItem = { BindTarget = selectedItem }
|
|
||||||
});
|
|
||||||
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
|
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
|
||||||
|
|
||||||
AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely());
|
AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely());
|
||||||
@ -167,7 +205,8 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
public Live<BeatmapSetInfo> CurrentImport { get; private set; }
|
public Live<BeatmapSetInfo> CurrentImport { get; private set; }
|
||||||
|
|
||||||
public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources,
|
||||||
|
GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
||||||
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
@ -32,6 +35,9 @@ namespace osu.Game.Online.Rooms
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private RealmAccess realm { get; set; } = null!;
|
private RealmAccess realm { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The availability state of the currently selected playlist item.
|
/// The availability state of the currently selected playlist item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -58,39 +64,50 @@ namespace osu.Game.Online.Rooms
|
|||||||
|
|
||||||
downloadTracker?.RemoveAndDisposeImmediately();
|
downloadTracker?.RemoveAndDisposeImmediately();
|
||||||
|
|
||||||
Debug.Assert(item.NewValue.Beatmap.Value.BeatmapSet != null);
|
beatmapLookupCache.GetBeatmapAsync(item.NewValue.Beatmap.Value.OnlineID).ContinueWith(task => Schedule(() =>
|
||||||
|
|
||||||
downloadTracker = new BeatmapDownloadTracker(item.NewValue.Beatmap.Value.BeatmapSet);
|
|
||||||
|
|
||||||
AddInternal(downloadTracker);
|
|
||||||
|
|
||||||
downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability), true);
|
|
||||||
downloadTracker.Progress.BindValueChanged(_ =>
|
|
||||||
{
|
{
|
||||||
if (downloadTracker.State.Value != DownloadState.Downloading)
|
var beatmap = task.GetResultSafely();
|
||||||
return;
|
|
||||||
|
|
||||||
// incoming progress changes are going to be at a very high rate.
|
if (SelectedItem.Value?.Beatmap.Value.OnlineID == beatmap.OnlineID)
|
||||||
// we don't want to flood the network with this, so rate limit how often we send progress updates.
|
beginTracking(beatmap);
|
||||||
if (progressUpdate?.Completed != false)
|
}), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||||
progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
// handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
|
|
||||||
realmSubscription?.Dispose();
|
|
||||||
realmSubscription = realm.RegisterForNotifications(r => QueryBeatmapForOnlinePlay(r, SelectedItem.Value.Beatmap.Value), (items, changes, ___) =>
|
|
||||||
{
|
|
||||||
if (changes == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Scheduler.AddOnce(updateAvailability);
|
|
||||||
});
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAvailability()
|
private void beginTracking(APIBeatmap beatmap)
|
||||||
{
|
{
|
||||||
if (downloadTracker == null || SelectedItem.Value == null)
|
Debug.Assert(beatmap.BeatmapSet != null);
|
||||||
|
|
||||||
|
downloadTracker = new BeatmapDownloadTracker(beatmap.BeatmapSet);
|
||||||
|
|
||||||
|
AddInternal(downloadTracker);
|
||||||
|
|
||||||
|
downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability, beatmap), true);
|
||||||
|
downloadTracker.Progress.BindValueChanged(_ =>
|
||||||
|
{
|
||||||
|
if (downloadTracker.State.Value != DownloadState.Downloading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// incoming progress changes are going to be at a very high rate.
|
||||||
|
// we don't want to flood the network with this, so rate limit how often we send progress updates.
|
||||||
|
if (progressUpdate?.Completed != false)
|
||||||
|
progressUpdate = Scheduler.AddDelayed(updateAvailability, beatmap, progressUpdate == null ? 0 : 500);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
|
||||||
|
realmSubscription?.Dispose();
|
||||||
|
realmSubscription = realm.RegisterForNotifications(r => QueryBeatmapForOnlinePlay(r, SelectedItem.Value.Beatmap.Value), (items, changes, ___) =>
|
||||||
|
{
|
||||||
|
if (changes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Scheduler.AddOnce(updateAvailability, beatmap);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAvailability(APIBeatmap beatmap)
|
||||||
|
{
|
||||||
|
if (downloadTracker == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (downloadTracker.State.Value)
|
switch (downloadTracker.State.Value)
|
||||||
@ -108,7 +125,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DownloadState.LocallyAvailable:
|
case DownloadState.LocallyAvailable:
|
||||||
bool available = QueryBeatmapForOnlinePlay(realm.Realm, SelectedItem.Value.Beatmap.Value).Any();
|
bool available = QueryBeatmapForOnlinePlay(realm.Realm, beatmap).Any();
|
||||||
|
|
||||||
availability.Value = available ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
|
availability.Value = available ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user