1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 23:12:56 +08:00

Merge remote-tracking branch 'upstream/master' into lighten-playfield-during-breaks

This commit is contained in:
Dean Herbert 2019-12-12 19:55:09 +09:00
commit 7559012fb7
37 changed files with 254 additions and 317 deletions

View File

@ -54,6 +54,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.1210.1" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.1212.0" />
</ItemGroup>
</Project>

View File

@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Catch.Tests
RelativeSizeAxes = Axes.Both,
Children = new[]
{
drawableRuleset = new DrawableCatchRuleset(new CatchRuleset(), beatmap, Array.Empty<Mod>())
drawableRuleset = new DrawableCatchRuleset(new CatchRuleset(), beatmap.GetPlayableBeatmap(new CatchRuleset().RulesetInfo))
}
});

View File

@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch
{
public class CatchRuleset : Ruleset
{
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableCatchRuleset(this, beatmap, mods);
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableCatchRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);

View File

@ -2,23 +2,21 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Catch.Scoring
{
public class CatchScoreProcessor : ScoreProcessor<CatchHitObject>
public class CatchScoreProcessor : ScoreProcessor
{
public CatchScoreProcessor(DrawableRuleset<CatchHitObject> drawableRuleset)
: base(drawableRuleset)
public CatchScoreProcessor(IBeatmap beatmap)
: base(beatmap)
{
}
private float hpDrainRate;
protected override void ApplyBeatmap(Beatmap<CatchHitObject> beatmap)
protected override void ApplyBeatmap(IBeatmap beatmap)
{
base.ApplyBeatmap(beatmap);

View File

@ -25,14 +25,14 @@ namespace osu.Game.Rulesets.Catch.UI
protected override bool UserScrollSpeedAdjustment => false;
public DrawableCatchRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableCatchRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
Direction.Value = ScrollingDirection.Down;
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
}
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this);
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(Beatmap);
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit
{
public new IScrollingInfo ScrollingInfo => base.ScrollingInfo;
public DrawableManiaEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableManiaEditRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods)
{
}

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Edit
public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns;
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
{
drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods);

View File

@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania
{
public class ManiaRuleset : Ruleset
{
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableManiaRuleset(this, beatmap, mods);
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableManiaRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score);

View File

@ -3,13 +3,11 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mania.Scoring
{
internal class ManiaScoreProcessor : ScoreProcessor<ManiaHitObject>
internal class ManiaScoreProcessor : ScoreProcessor
{
/// <summary>
/// The hit HP multiplier at OD = 0.
@ -51,12 +49,12 @@ namespace osu.Game.Rulesets.Mania.Scoring
/// </summary>
private double hpMultiplier = 1;
public ManiaScoreProcessor(DrawableRuleset<ManiaHitObject> drawableRuleset)
: base(drawableRuleset)
public ManiaScoreProcessor(IBeatmap beatmap)
: base(beatmap)
{
}
protected override void ApplyBeatmap(Beatmap<ManiaHitObject> beatmap)
protected override void ApplyBeatmap(IBeatmap beatmap)
{
base.ApplyBeatmap(beatmap);
@ -65,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Scoring
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max);
}
protected override void SimulateAutoplay(Beatmap<ManiaHitObject> beatmap)
protected override void SimulateAutoplay(IBeatmap beatmap)
{
while (true)
{

View File

@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.UI
private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>();
public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
BarLines = new BarLineGenerator<BarLine>(Beatmap).BarLines;
@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Mania.UI
protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(Beatmap);
public override int Variant => (int)(Beatmap.Stages.Count == 1 ? PlayfieldType.Single : PlayfieldType.Dual) + Beatmap.TotalColumns;

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Edit
/// </summary>
private const double editor_hit_object_fade_out_extension = 500;
public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableOsuEditRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods)
{
}

View File

@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
}
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
=> new DrawableOsuEditRuleset(ruleset, beatmap, mods);
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]

View File

@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu
{
public class OsuRuleset : Ruleset
{
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableOsuRuleset(this, beatmap, mods);
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableOsuRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);

View File

@ -5,22 +5,20 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Osu.Scoring
{
internal class OsuScoreProcessor : ScoreProcessor<OsuHitObject>
internal class OsuScoreProcessor : ScoreProcessor
{
public OsuScoreProcessor(DrawableRuleset<OsuHitObject> drawableRuleset)
: base(drawableRuleset)
public OsuScoreProcessor(IBeatmap beatmap)
: base(beatmap)
{
}
private float hpDrainRate;
protected override void ApplyBeatmap(Beatmap<OsuHitObject> beatmap)
protected override void ApplyBeatmap(IBeatmap beatmap)
{
base.ApplyBeatmap(beatmap);

View File

@ -26,14 +26,14 @@ namespace osu.Game.Rulesets.Osu.UI
{
protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config;
public DrawableOsuRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableOsuRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // always show the gameplay cursor
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this);
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(Beatmap);
protected override Playfield CreatePlayfield() => new OsuPlayfield();

View File

@ -11,7 +11,6 @@ using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
@ -91,7 +90,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = 768,
Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap, Array.Empty<Mod>()) }
Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap.GetPlayableBeatmap(new TaikoRuleset().RulesetInfo)) }
});
}

View File

@ -1,15 +1,15 @@
// 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.
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Taiko.Scoring
{
internal class TaikoScoreProcessor : ScoreProcessor<TaikoHitObject>
internal class TaikoScoreProcessor : ScoreProcessor
{
/// <summary>
/// A value used for calculating <see cref="hpMultiplier"/>.
@ -31,16 +31,16 @@ namespace osu.Game.Rulesets.Taiko.Scoring
/// </summary>
private double hpMissMultiplier;
public TaikoScoreProcessor(DrawableRuleset<TaikoHitObject> drawableRuleset)
: base(drawableRuleset)
public TaikoScoreProcessor(IBeatmap beatmap)
: base(beatmap)
{
}
protected override void ApplyBeatmap(Beatmap<TaikoHitObject> beatmap)
protected override void ApplyBeatmap(IBeatmap beatmap)
{
base.ApplyBeatmap(beatmap);
hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.OfType<Hit>().Count() * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
}

View File

@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko
{
public class TaikoRuleset : Ruleset
{
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableTaikoRuleset(this, beatmap, mods);
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new DrawableTaikoRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
public const string SHORT_NAME = "taiko";

View File

@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.UI
protected override bool UserScrollSpeedAdjustment => false;
public DrawableTaikoRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
Direction.Value = ScrollingDirection.Left;
@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.UI
new BarLineGenerator<BarLine>(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar)));
}
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(Beatmap);
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer();

View File

@ -172,7 +172,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
var ruleset = new TestScrollingRuleset();
drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap), Array.Empty<Mod>());
drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap).GetPlayableBeatmap(ruleset.RulesetInfo));
drawableRuleset.FrameStablePlayback = false;
overrideAction?.Invoke(drawableRuleset);
@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override IEnumerable<Mod> GetModsFor(ModType type) => throw new NotImplementedException();
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new TestDrawableScrollingRuleset(this, beatmap, mods);
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => new TestDrawableScrollingRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap);
@ -222,7 +222,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public new Bindable<double> TimeRange => base.TimeRange;
public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public TestDrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
TimeRange.Value = time_range;

View File

@ -57,7 +57,7 @@ namespace osu.Game.Beatmaps
{
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] { };
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
{
throw new NotImplementedException();
}

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using osu.Framework.IO.File;
using osu.Framework.Extensions;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Beatmaps.ControlPoints;
@ -112,7 +112,7 @@ namespace osu.Game.Beatmaps.Formats
switch (pair.Key)
{
case @"AudioFilename":
metadata.AudioFile = FileSafety.PathStandardise(pair.Value);
metadata.AudioFile = pair.Value.ToStandardisedPath();
break;
case @"AudioLeadIn":
@ -300,12 +300,12 @@ namespace osu.Game.Beatmaps.Formats
{
case EventType.Background:
string bgFilename = split[2].Trim('"');
beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename);
beatmap.BeatmapInfo.Metadata.BackgroundFile = bgFilename.ToStandardisedPath();
break;
case EventType.Video:
string videoFilename = split[2].Trim('"');
beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename);
beatmap.BeatmapInfo.Metadata.VideoFile = videoFilename.ToStandardisedPath();
break;
case EventType.Break:

View File

@ -8,8 +8,8 @@ using System.IO;
using System.Linq;
using osuTK;
using osuTK.Graphics;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.IO.File;
using osu.Game.IO;
using osu.Game.Storyboards;
@ -335,6 +335,6 @@ namespace osu.Game.Beatmaps.Formats
}
}
private string cleanFilename(string path) => FileSafety.PathStandardise(path.Trim('"'));
private string cleanFilename(string path) => path.Trim('"').ToStandardisedPath();
}
}

View File

@ -62,6 +62,6 @@ namespace osu.Game.Beatmaps
/// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param>
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods);
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null);
}
}

View File

@ -7,7 +7,6 @@ using osu.Game.Rulesets.Mods;
using System;
using System.Collections.Generic;
using osu.Game.Storyboards;
using osu.Framework.IO.File;
using System.IO;
using System.Linq;
using System.Threading;
@ -83,7 +82,10 @@ namespace osu.Game.Beatmaps
/// <returns>The absolute path of the output file.</returns>
public string Save()
{
var path = FileSafety.GetTempPath(Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json");
string directory = Path.Combine(Path.GetTempPath(), @"osu!");
Directory.CreateDirectory(directory);
var path = Path.Combine(directory, Guid.NewGuid().ToString().Replace("-", string.Empty) + ".json");
using (var sw = new StreamWriter(path))
sw.WriteLine(Beatmap.Serialize());
return path;
@ -97,8 +99,10 @@ namespace osu.Game.Beatmaps
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods)
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null)
{
mods ??= Array.Empty<Mod>();
var rulesetInstance = ruleset.CreateInstance();
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);

View File

@ -13,7 +13,6 @@ using Microsoft.EntityFrameworkCore;
using osu.Framework;
using osu.Framework.Extensions;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.IO.File;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Threading;
@ -493,7 +492,7 @@ namespace osu.Game.Database
{
fileInfos.Add(new TFileModel
{
Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)),
Filename = file.Substring(prefix.Length).ToStandardisedPath(),
FileInfo = files.Add(s)
});
}

View File

@ -149,7 +149,15 @@ namespace osu.Game.Database
lock (writeLock)
{
recycleThreadContexts();
storage.DeleteDatabase(database_name);
try
{
storage.DeleteDatabase(database_name);
}
catch
{
// for now we are not sure why file handles are kept open by EF, but this is generally only used in testing
}
}
}
}

View File

@ -48,7 +48,6 @@ namespace osu.Game.Rulesets.Edit
[Resolved]
private BindableBeatDivisor beatDivisor { get; set; }
private IWorkingBeatmap workingBeatmap;
private Beatmap<TObject> playableBeatmap;
private IBeatmapProcessor beatmapProcessor;
@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Edit
{
try
{
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, workingBeatmap, Array.Empty<Mod>()))
drawableRulesetWrapper = new DrawableEditRulesetWrapper<TObject>(CreateDrawableRuleset(Ruleset, playableBeatmap))
{
Clock = framedClock,
ProcessCustomClock = false
@ -145,8 +144,7 @@ namespace osu.Game.Rulesets.Edit
{
var parentWorkingBeatmap = parent.Get<IBindable<WorkingBeatmap>>().Value;
playableBeatmap = (Beatmap<TObject>)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo, Array.Empty<Mod>());
workingBeatmap = new EditorWorkingBeatmap<TObject>(playableBeatmap, parentWorkingBeatmap);
playableBeatmap = (Beatmap<TObject>)parentWorkingBeatmap.GetPlayableBeatmap(Ruleset.RulesetInfo);
beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap);
@ -250,7 +248,7 @@ namespace osu.Game.Rulesets.Edit
protected abstract IReadOnlyList<HitObjectCompositionTool> CompositionTools { get; }
protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods);
protected abstract DrawableRuleset<TObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null);
public void BeginPlacement(HitObject hitObject)
{

View File

@ -60,7 +60,7 @@ namespace osu.Game.Rulesets
/// <param name="mods">The <see cref="Mod"/>s to apply.</param>
/// <exception cref="BeatmapInvalidForRulesetException">Unable to successfully load the beatmap to be usable with this ruleset.</exception>
/// <returns></returns>
public abstract DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods);
public abstract DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null);
/// <summary>
/// Creates a <see cref="IBeatmapConverter"/> to convert a <see cref="IBeatmap"/> to one that is applicable for this <see cref="Ruleset"/>.

View File

@ -13,13 +13,16 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Scoring
{
public abstract class ScoreProcessor
public class ScoreProcessor
{
private const double base_portion = 0.3;
private const double combo_portion = 0.7;
private const double max_score = 1000000;
/// <summary>
/// Invoked when the <see cref="ScoreProcessor"/> is in a failed state.
/// This may occur regardless of whether an <see cref="AllJudged"/> event is invoked.
@ -67,11 +70,6 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
public readonly Bindable<IReadOnlyList<Mod>> Mods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
/// <summary>
/// Create a <see cref="HitWindows"/> for this processor.
/// </summary>
public virtual HitWindows CreateHitWindows() => new HitWindows();
/// <summary>
/// The current rank.
/// </summary>
@ -90,132 +88,23 @@ namespace osu.Game.Rulesets.Scoring
/// <summary>
/// Whether all <see cref="Judgement"/>s have been processed.
/// </summary>
public virtual bool HasCompleted => false;
/// <summary>
/// The total number of judged <see cref="HitObject"/>s at the current point in time.
/// </summary>
public int JudgedHits { get; protected set; }
public bool HasCompleted => JudgedHits == MaxHits;
/// <summary>
/// Whether this ScoreProcessor has already triggered the failed state.
/// </summary>
public virtual bool HasFailed { get; private set; }
public bool HasFailed { get; private set; }
/// <summary>
/// The default conditions for failing.
/// The maximum number of hits that can be judged.
/// </summary>
protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value);
protected ScoreProcessor()
{
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
Accuracy.ValueChanged += delegate
{
Rank.Value = rankFrom(Accuracy.Value);
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
Rank.Value = mod.AdjustRank(Rank.Value, Accuracy.Value);
};
}
private ScoreRank rankFrom(double acc)
{
if (acc == 1)
return ScoreRank.X;
if (acc > 0.95)
return ScoreRank.S;
if (acc > 0.9)
return ScoreRank.A;
if (acc > 0.8)
return ScoreRank.B;
if (acc > 0.7)
return ScoreRank.C;
return ScoreRank.D;
}
/// <summary>
/// Resets this ScoreProcessor to a default state.
/// </summary>
/// <param name="storeResults">Whether to store the current state of the <see cref="ScoreProcessor"/> for future use.</param>
protected virtual void Reset(bool storeResults)
{
TotalScore.Value = 0;
Accuracy.Value = 1;
Health.Value = 1;
Combo.Value = 0;
Rank.Value = ScoreRank.X;
HighestCombo.Value = 0;
JudgedHits = 0;
HasFailed = false;
}
/// <summary>
/// Checks if the score is in a failed state and notifies subscribers.
/// <para>
/// This can only ever notify subscribers once.
/// </para>
/// </summary>
protected void UpdateFailed(JudgementResult result)
{
if (HasFailed)
return;
if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true)
return;
if (Failed?.Invoke() != false)
HasFailed = true;
}
/// <summary>
/// Notifies subscribers of <see cref="NewJudgement"/> that a new judgement has occurred.
/// </summary>
/// <param name="result">The judgement scoring result to notify subscribers of.</param>
protected void NotifyNewJudgement(JudgementResult result)
{
NewJudgement?.Invoke(result);
if (HasCompleted)
AllJudged?.Invoke();
}
/// <summary>
/// Retrieve a score populated with data for the current play this processor is responsible for.
/// </summary>
public virtual void PopulateScore(ScoreInfo score)
{
score.TotalScore = (long)Math.Round(TotalScore.Value);
score.Combo = Combo.Value;
score.MaxCombo = HighestCombo.Value;
score.Accuracy = Math.Round(Accuracy.Value, 4);
score.Rank = Rank.Value;
score.Date = DateTimeOffset.Now;
var hitWindows = CreateHitWindows();
foreach (var result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r)))
score.Statistics[result] = GetStatistic(result);
}
public abstract int GetStatistic(HitResult result);
public abstract double GetStandardisedScore();
}
public class ScoreProcessor<TObject> : ScoreProcessor
where TObject : HitObject
{
private const double base_portion = 0.3;
private const double combo_portion = 0.7;
private const double max_score = 1000000;
public sealed override bool HasCompleted => JudgedHits == MaxHits;
protected int MaxHits { get; private set; }
/// <summary>
/// The total number of judged <see cref="HitObject"/>s at the current point in time.
/// </summary>
public int JudgedHits { get; private set; }
private double maxHighestCombo;
private double maxBaseScore;
@ -225,17 +114,22 @@ namespace osu.Game.Rulesets.Scoring
private double scoreMultiplier = 1;
public ScoreProcessor(DrawableRuleset<TObject> drawableRuleset)
public ScoreProcessor(IBeatmap beatmap)
{
Debug.Assert(base_portion + combo_portion == 1.0);
drawableRuleset.OnNewResult += applyResult;
drawableRuleset.OnRevertResult += revertResult;
Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue);
Accuracy.ValueChanged += accuracy =>
{
Rank.Value = rankFrom(accuracy.NewValue);
foreach (var mod in Mods.Value.OfType<IApplicableToScoreProcessor>())
Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
};
ApplyBeatmap(drawableRuleset.Beatmap);
ApplyBeatmap(beatmap);
Reset(false);
SimulateAutoplay(drawableRuleset.Beatmap);
SimulateAutoplay(beatmap);
Reset(true);
if (maxBaseScore == 0 || maxHighestCombo == 0)
@ -257,19 +151,19 @@ namespace osu.Game.Rulesets.Scoring
}
/// <summary>
/// Applies any properties of the <see cref="Beatmap{TObject}"/> which affect scoring to this <see cref="ScoreProcessor{TObject}"/>.
/// Applies any properties of the <see cref="IBeatmap"/> which affect scoring to this <see cref="ScoreProcessor"/>.
/// </summary>
/// <param name="beatmap">The <see cref="Beatmap{TObject}"/> to read properties from.</param>
protected virtual void ApplyBeatmap(Beatmap<TObject> beatmap)
/// <param name="beatmap">The <see cref="IBeatmap"/> to read properties from.</param>
protected virtual void ApplyBeatmap(IBeatmap beatmap)
{
}
/// <summary>
/// Simulates an autoplay of the <see cref="Beatmap{TObject}"/> to determine scoring values.
/// Simulates an autoplay of the <see cref="IBeatmap"/> to determine scoring values.
/// </summary>
/// <remarks>This provided temporarily. DO NOT USE.</remarks>
/// <param name="beatmap">The <see cref="Beatmap{TObject}"/> to simulate.</param>
protected virtual void SimulateAutoplay(Beatmap<TObject> beatmap)
/// <param name="beatmap">The <see cref="IBeatmap"/> to simulate.</param>
protected virtual void SimulateAutoplay(IBeatmap beatmap)
{
foreach (var obj in beatmap.HitObjects)
simulate(obj);
@ -289,7 +183,7 @@ namespace osu.Game.Rulesets.Scoring
result.Type = judgement.MaxResult;
applyResult(result);
ApplyResult(result);
}
}
@ -297,22 +191,26 @@ namespace osu.Game.Rulesets.Scoring
/// Applies the score change of a <see cref="JudgementResult"/> to this <see cref="ScoreProcessor"/>.
/// </summary>
/// <param name="result">The <see cref="JudgementResult"/> to apply.</param>
private void applyResult(JudgementResult result)
public void ApplyResult(JudgementResult result)
{
ApplyResult(result);
updateScore();
ApplyResultInternal(result);
UpdateFailed(result);
NotifyNewJudgement(result);
updateScore();
updateFailed(result);
NewJudgement?.Invoke(result);
if (HasCompleted)
AllJudged?.Invoke();
}
/// <summary>
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/>.
/// </summary>
/// <param name="result">The judgement scoring result.</param>
private void revertResult(JudgementResult result)
public void RevertResult(JudgementResult result)
{
RevertResult(result);
RevertResultInternal(result);
updateScore();
}
@ -322,10 +220,10 @@ namespace osu.Game.Rulesets.Scoring
/// Applies the score change of a <see cref="JudgementResult"/> to this <see cref="ScoreProcessor"/>.
/// </summary>
/// <remarks>
/// Any changes applied via this method can be reverted via <see cref="RevertResult"/>.
/// Any changes applied via this method can be reverted via <see cref="RevertResultInternal"/>.
/// </remarks>
/// <param name="result">The <see cref="JudgementResult"/> to apply.</param>
protected virtual void ApplyResult(JudgementResult result)
protected virtual void ApplyResultInternal(JudgementResult result)
{
result.ComboAtJudgement = Combo.Value;
result.HighestComboAtJudgement = HighestCombo.Value;
@ -372,10 +270,10 @@ namespace osu.Game.Rulesets.Scoring
}
/// <summary>
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/> via <see cref="ApplyResult"/>.
/// Reverts the score change of a <see cref="JudgementResult"/> that was applied to this <see cref="ScoreProcessor"/> via <see cref="ApplyResultInternal"/>.
/// </summary>
/// <param name="result">The judgement scoring result.</param>
protected virtual void RevertResult(JudgementResult result)
protected virtual void RevertResultInternal(JudgementResult result)
{
Combo.Value = result.ComboAtJudgement;
HighestCombo.Value = result.HighestComboAtJudgement;
@ -432,11 +330,49 @@ namespace osu.Game.Rulesets.Scoring
}
}
public override int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result);
/// <summary>
/// Checks if the score is in a failed state and notifies subscribers.
/// <para>
/// This can only ever notify subscribers once.
/// </para>
/// </summary>
private void updateFailed(JudgementResult result)
{
if (HasFailed)
return;
public override double GetStandardisedScore() => getScore(ScoringMode.Standardised);
if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true)
return;
protected override void Reset(bool storeResults)
if (Failed?.Invoke() != false)
HasFailed = true;
}
private ScoreRank rankFrom(double acc)
{
if (acc == 1)
return ScoreRank.X;
if (acc > 0.95)
return ScoreRank.S;
if (acc > 0.9)
return ScoreRank.A;
if (acc > 0.8)
return ScoreRank.B;
if (acc > 0.7)
return ScoreRank.C;
return ScoreRank.D;
}
public int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result);
public double GetStandardisedScore() => getScore(ScoringMode.Standardised);
/// <summary>
/// Resets this ScoreProcessor to a default state.
/// </summary>
/// <param name="storeResults">Whether to store the current state of the <see cref="ScoreProcessor"/> for future use.</param>
protected virtual void Reset(bool storeResults)
{
scoreResultCounts.Clear();
@ -447,13 +383,49 @@ namespace osu.Game.Rulesets.Scoring
maxBaseScore = baseScore;
}
base.Reset(storeResults);
JudgedHits = 0;
baseScore = 0;
rollingMaxBaseScore = 0;
bonusScore = 0;
TotalScore.Value = 0;
Accuracy.Value = 1;
Health.Value = 1;
Combo.Value = 0;
Rank.Value = ScoreRank.X;
HighestCombo.Value = 0;
HasFailed = false;
}
/// <summary>
/// Retrieve a score populated with data for the current play this processor is responsible for.
/// </summary>
public virtual void PopulateScore(ScoreInfo score)
{
score.TotalScore = (long)Math.Round(TotalScore.Value);
score.Combo = Combo.Value;
score.MaxCombo = HighestCombo.Value;
score.Accuracy = Math.Round(Accuracy.Value, 4);
score.Rank = Rank.Value;
score.Date = DateTimeOffset.Now;
var hitWindows = CreateHitWindows();
foreach (var result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r)))
score.Statistics[result] = GetStatistic(result);
}
/// <summary>
/// The default conditions for failing.
/// </summary>
protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value);
/// <summary>
/// Create a <see cref="HitWindows"/> for this processor.
/// </summary>
public virtual HitWindows CreateHitWindows() => new HitWindows();
/// <summary>
/// Creates the <see cref="JudgementResult"/> that represents the scoring result for a <see cref="HitObject"/>.
/// </summary>

View File

@ -45,6 +45,10 @@ namespace osu.Game.Rulesets.UI
public abstract class DrawableRuleset<TObject> : DrawableRuleset, IProvideCursor, ICanAttachKeyCounter
where TObject : HitObject
{
public override event Action<JudgementResult> OnNewResult;
public override event Action<JudgementResult> OnRevertResult;
/// <summary>
/// The selected variant.
/// </summary>
@ -91,20 +95,10 @@ namespace osu.Game.Rulesets.UI
}
}
/// <summary>
/// Invoked when a <see cref="JudgementResult"/> has been applied by a <see cref="DrawableHitObject"/>.
/// </summary>
public event Action<JudgementResult> OnNewResult;
/// <summary>
/// Invoked when a <see cref="JudgementResult"/> is being reverted by a <see cref="DrawableHitObject"/>.
/// </summary>
public event Action<JudgementResult> OnRevertResult;
/// <summary>
/// The beatmap.
/// </summary>
public Beatmap<TObject> Beatmap;
public readonly Beatmap<TObject> Beatmap;
public override IEnumerable<HitObject> Objects => Beatmap.HitObjects;
@ -124,20 +118,22 @@ namespace osu.Game.Rulesets.UI
/// Creates a ruleset visualisation for the provided ruleset and beatmap.
/// </summary>
/// <param name="ruleset">The ruleset being represented.</param>
/// <param name="workingBeatmap">The beatmap to create the hit renderer for.</param>
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
/// <param name="mods">The <see cref="Mod"/>s to apply.</param>
protected DrawableRuleset(Ruleset ruleset, IWorkingBeatmap workingBeatmap, IReadOnlyList<Mod> mods)
protected DrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset)
{
if (workingBeatmap == null)
throw new ArgumentException("Beatmap cannot be null.", nameof(workingBeatmap));
if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap), "Beatmap cannot be null.");
this.mods = mods.ToArray();
if (!(beatmap is Beatmap<TObject> tBeatmap))
throw new ArgumentException($"{GetType()} expected the beatmap to contain hitobjects of type {typeof(TObject)}.", nameof(beatmap));
Beatmap = tBeatmap;
this.mods = mods?.ToArray() ?? Array.Empty<Mod>();
RelativeSizeAxes = Axes.Both;
Beatmap = (Beatmap<TObject>)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo, mods);
KeyBindingInputManager = CreateInputManager();
playfield = new Lazy<Playfield>(CreatePlayfield);
@ -309,7 +305,7 @@ namespace osu.Game.Rulesets.UI
/// <returns>The Playfield.</returns>
protected abstract Playfield CreatePlayfield();
public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor<TObject>(this);
public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(Beatmap);
/// <summary>
/// Applies the active mods to this DrawableRuleset.
@ -366,6 +362,16 @@ namespace osu.Game.Rulesets.UI
/// </summary>
public abstract class DrawableRuleset : CompositeDrawable
{
/// <summary>
/// Invoked when a <see cref="JudgementResult"/> has been applied by a <see cref="DrawableHitObject"/>.
/// </summary>
public abstract event Action<JudgementResult> OnNewResult;
/// <summary>
/// Invoked when a <see cref="JudgementResult"/> is being reverted by a <see cref="DrawableHitObject"/>.
/// </summary>
public abstract event Action<JudgementResult> OnRevertResult;
/// <summary>
/// Whether a replay is currently loaded.
/// </summary>

View File

@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
[Cached(Type = typeof(IScrollingInfo))]
private readonly LocalScrollingInfo scrollingInfo;
protected DrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
protected DrawableScrollingRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods)
{
scrollingInfo = new LocalScrollingInfo();

View File

@ -4,7 +4,6 @@
using System;
using osuTK.Graphics;
using osu.Framework.Screens;
using osu.Game.Screens.Backgrounds;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -29,14 +28,13 @@ using osu.Game.Input.Bindings;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Screens.Edit.Setup;
using osu.Game.Screens.Edit.Timing;
using osu.Game.Screens.Play;
using osu.Game.Users;
namespace osu.Game.Screens.Edit
{
public class Editor : OsuScreen, IKeyBindingHandler<GlobalAction>
public class Editor : ScreenWithBeatmapBackground, IKeyBindingHandler<GlobalAction>
{
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
public override float BackgroundParallaxAmount => 0.1f;
public override bool AllowBackButton => false;
@ -250,8 +248,12 @@ namespace osu.Game.Screens.Edit
{
base.OnEntering(last);
// todo: temporary. we want to be applying dim using the UserDimContainer eventually.
Background.FadeColour(Color4.DarkGray, 500);
Background.EnableUserDim.Value = false;
Background.BlurAmount.Value = 0;
resetTrack(true);
}

View File

@ -1,49 +0,0 @@
// 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.
using System.Collections.Generic;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Video;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Skinning;
using osu.Game.Storyboards;
namespace osu.Game.Screens.Edit
{
/// <summary>
/// Encapsulates a <see cref="WorkingBeatmap"/> while providing an overridden <see cref="Beatmap{TObject}"/>.
/// </summary>
/// <typeparam name="TObject"></typeparam>
public class EditorWorkingBeatmap<TObject> : IWorkingBeatmap
where TObject : HitObject
{
private readonly Beatmap<TObject> playableBeatmap;
private readonly WorkingBeatmap workingBeatmap;
public EditorWorkingBeatmap(Beatmap<TObject> playableBeatmap, WorkingBeatmap workingBeatmap)
{
this.playableBeatmap = playableBeatmap;
this.workingBeatmap = workingBeatmap;
}
public IBeatmap Beatmap => workingBeatmap.Beatmap;
public Texture Background => workingBeatmap.Background;
public VideoSprite Video => workingBeatmap.Video;
public Track Track => workingBeatmap.Track;
public Waveform Waveform => workingBeatmap.Waveform;
public Storyboard Storyboard => workingBeatmap.Storyboard;
public ISkin Skin => workingBeatmap.Skin;
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods) => playableBeatmap;
}
}

View File

@ -114,32 +114,40 @@ namespace osu.Game.Screens.Play
Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray();
WorkingBeatmap working = loadBeatmap();
if (Beatmap.Value is DummyWorkingBeatmap)
return;
if (working == null)
IBeatmap playableBeatmap = loadPlayableBeatmap();
if (playableBeatmap == null)
return;
sampleRestart = audio.Samples.Get(@"Gameplay/restart");
mouseWheelDisabled = config.GetBindable<bool>(OsuSetting.MouseDisableWheel);
DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
ScoreProcessor = DrawableRuleset.CreateScoreProcessor();
ScoreProcessor.Mods.BindTo(Mods);
if (!ScoreProcessor.Mode.Disabled)
config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime);
InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime);
addUnderlayComponents(GameplayClockContainer);
addGameplayComponents(GameplayClockContainer, working);
addOverlayComponents(GameplayClockContainer, working);
addGameplayComponents(GameplayClockContainer, Beatmap.Value);
addOverlayComponents(GameplayClockContainer, Beatmap.Value);
DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true);
// bind clock into components that require it
DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused);
DrawableRuleset.OnNewResult += ScoreProcessor.ApplyResult;
DrawableRuleset.OnRevertResult += ScoreProcessor.RevertResult;
// Bind ScoreProcessor to ourselves
ScoreProcessor.AllJudged += onCompletion;
ScoreProcessor.Failed += onFail;
@ -247,36 +255,32 @@ namespace osu.Game.Screens.Play
&& !DrawableRuleset.HasReplayLoaded.Value
&& !breakOverlay.IsBreakTime.Value;
private WorkingBeatmap loadBeatmap()
private IBeatmap loadPlayableBeatmap()
{
WorkingBeatmap working = Beatmap.Value;
if (working is DummyWorkingBeatmap)
return null;
IBeatmap playable;
try
{
var beatmap = working.Beatmap;
if (beatmap == null)
if (Beatmap.Value.Beatmap == null)
throw new InvalidOperationException("Beatmap was not loaded");
rulesetInfo = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
ruleset = rulesetInfo.CreateInstance();
try
{
DrawableRuleset = ruleset.CreateDrawableRulesetWith(working, Mods.Value);
playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Mods.Value);
}
catch (BeatmapInvalidForRulesetException)
{
// we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset
// let's try again forcing the beatmap's ruleset.
rulesetInfo = beatmap.BeatmapInfo.Ruleset;
// A playable beatmap may not be creatable with the user's preferred ruleset, so try using the beatmap's default ruleset
rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset;
ruleset = rulesetInfo.CreateInstance();
DrawableRuleset = ruleset.CreateDrawableRulesetWith(Beatmap.Value, Mods.Value);
playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, Mods.Value);
}
if (!DrawableRuleset.Objects.Any())
if (playable.HitObjects.Count == 0)
{
Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error);
return null;
@ -289,7 +293,7 @@ namespace osu.Game.Screens.Play
return null;
}
return working;
return playable;
}
private void performImmediateExit()

View File

@ -23,7 +23,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.1210.1" />
<PackageReference Include="ppy.osu.Framework" Version="2019.1212.0" />
<PackageReference Include="Sentry" Version="1.2.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" />

View File

@ -74,7 +74,7 @@
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.1010.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1210.1" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.1212.0" />
</ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
<ItemGroup Label="Transitive Dependencies">
@ -82,7 +82,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2019.1210.1" />
<PackageReference Include="ppy.osu.Framework" Version="2019.1212.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" />