mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 12:57:36 +08:00
79 lines
2.9 KiB
C#
79 lines
2.9 KiB
C#
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||
|
// See the LICENCE file in the repository root for full licence text.
|
||
|
|
||
|
#nullable enable
|
||
|
|
||
|
using System.Linq;
|
||
|
using System.Threading.Tasks;
|
||
|
using osu.Framework.Extensions;
|
||
|
using osu.Game.Database;
|
||
|
using osu.Game.Rulesets.Objects;
|
||
|
|
||
|
namespace osu.Game.Beatmaps
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Handles all processing required to ensure a local beatmap is in a consistent state with any changes.
|
||
|
/// </summary>
|
||
|
public class BeatmapUpdater
|
||
|
{
|
||
|
private readonly BeatmapManager beatmapManager;
|
||
|
private readonly BeatmapOnlineLookupQueue onlineLookupQueue;
|
||
|
private readonly BeatmapDifficultyCache difficultyCache;
|
||
|
|
||
|
public BeatmapUpdater(BeatmapManager beatmapManager, BeatmapOnlineLookupQueue onlineLookupQueue, BeatmapDifficultyCache difficultyCache)
|
||
|
{
|
||
|
this.beatmapManager = beatmapManager;
|
||
|
this.onlineLookupQueue = onlineLookupQueue;
|
||
|
this.difficultyCache = difficultyCache;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Queue a beatmap for background processing.
|
||
|
/// </summary>
|
||
|
public void Queue(Live<BeatmapSetInfo> beatmap)
|
||
|
{
|
||
|
// For now, just fire off a task.
|
||
|
// TODO: Add actual queueing probably.
|
||
|
Task.Factory.StartNew(() => beatmap.PerformRead(Process));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Run all processing on a beatmap immediately.
|
||
|
/// </summary>
|
||
|
public void Process(BeatmapSetInfo beatmapSet)
|
||
|
{
|
||
|
beatmapSet.Realm.Write(() =>
|
||
|
{
|
||
|
onlineLookupQueue.Update(beatmapSet);
|
||
|
|
||
|
foreach (var beatmap in beatmapSet.Beatmaps)
|
||
|
{
|
||
|
var working = beatmapManager.GetWorkingBeatmap(beatmap);
|
||
|
|
||
|
// Because we aren't guaranteed all processing will happen on this thread, it's very hard to use the live realm object.
|
||
|
// This can be fixed by adding a synchronous flow to `BeatmapDifficultyCache`.
|
||
|
var detachedBeatmap = beatmap.Detach();
|
||
|
|
||
|
beatmap.StarRating = difficultyCache.GetDifficultyAsync(detachedBeatmap).GetResultSafely()?.Stars ?? 0;
|
||
|
beatmap.Length = calculateLength(working.Beatmap);
|
||
|
beatmap.BPM = 60000 / working.Beatmap.GetMostCommonBeatLength();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private double calculateLength(IBeatmap b)
|
||
|
{
|
||
|
if (!b.HitObjects.Any())
|
||
|
return 0;
|
||
|
|
||
|
var lastObject = b.HitObjects.Last();
|
||
|
|
||
|
//TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list).
|
||
|
double endTime = lastObject.GetEndTime();
|
||
|
double startTime = b.HitObjects.First().StartTime;
|
||
|
|
||
|
return endTime - startTime;
|
||
|
}
|
||
|
}
|
||
|
}
|