diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 910751a723..d48c9e9661 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -183,6 +183,19 @@ namespace osu.Desktop.Updater } }); } + + public override void Close() + { + // cancelling updates is not currently supported by the underlying updater. + // only allow dismissing for now. + + switch (State) + { + case ProgressNotificationState.Cancelled: + base.Close(); + break; + } + } } private class SquirrelLogger : Splat.ILogger, IDisposable diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 3c61eb19e5..459b8e1f6f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests var controlPointInfo = new ControlPointInfo(); controlPointInfo.Add(0, new TimingControlPoint()); - WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap + IWorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { HitObjects = new List { new Fruit() }, BeatmapInfo = new BeatmapInfo diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs index 4e05b1e3e0..39a58d336d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs @@ -1,12 +1,35 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyAttributes : DifficultyAttributes { + [JsonProperty("approach_rate")] public double ApproachRate { get; set; } + + public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + { + foreach (var v in base.ToDatabaseAttributes()) + yield return v; + + // Todo: osu!catch should not output star rating in the 'aim' attribute. + yield return (ATTRIB_ID_AIM, StarRating); + yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate); + yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); + } + + public override void FromDatabaseAttributes(IReadOnlyDictionary values) + { + base.FromDatabaseAttributes(values); + + StarRating = values[ATTRIB_ID_AIM]; + ApproachRate = values[ATTRIB_ID_APPROACH_RATE]; + MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; + } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs index 628d77107f..bfdef893e9 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -1,13 +1,38 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaDifficultyAttributes : DifficultyAttributes { + [JsonProperty("great_hit_window")] public double GreatHitWindow { get; set; } + + [JsonProperty("score_multiplier")] public double ScoreMultiplier { get; set; } + + public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + { + foreach (var v in base.ToDatabaseAttributes()) + yield return v; + + // Todo: osu!mania doesn't output MaxCombo attribute for some reason. + yield return (ATTRIB_ID_STRAIN, StarRating); + yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); + yield return (ATTRIB_ID_SCORE_MULTIPLIER, ScoreMultiplier); + } + + public override void FromDatabaseAttributes(IReadOnlyDictionary values) + { + base.FromDatabaseAttributes(values); + + StarRating = values[ATTRIB_ID_STRAIN]; + GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; + ScoreMultiplier = values[ATTRIB_ID_SCORE_MULTIPLIER]; + } } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index e0a216c8e0..4b2e54da17 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -1,21 +1,77 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuDifficultyAttributes : DifficultyAttributes { + [JsonProperty("aim_strain")] public double AimStrain { get; set; } + + [JsonProperty("speed_strain")] public double SpeedStrain { get; set; } + + [JsonProperty("flashlight_rating")] public double FlashlightRating { get; set; } + + [JsonProperty("slider_factor")] public double SliderFactor { get; set; } + + [JsonProperty("approach_rate")] public double ApproachRate { get; set; } + + [JsonProperty("overall_difficulty")] public double OverallDifficulty { get; set; } + public double DrainRate { get; set; } + public int HitCircleCount { get; set; } + public int SliderCount { get; set; } + public int SpinnerCount { get; set; } + + public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + { + foreach (var v in base.ToDatabaseAttributes()) + yield return v; + + yield return (ATTRIB_ID_AIM, AimStrain); + yield return (ATTRIB_ID_SPEED, SpeedStrain); + yield return (ATTRIB_ID_OVERALL_DIFFICULTY, OverallDifficulty); + yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate); + yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); + yield return (ATTRIB_ID_STRAIN, StarRating); + + if (ShouldSerializeFlashlightRating()) + yield return (ATTRIB_ID_FLASHLIGHT, FlashlightRating); + + yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor); + } + + public override void FromDatabaseAttributes(IReadOnlyDictionary values) + { + base.FromDatabaseAttributes(values); + + AimStrain = values[ATTRIB_ID_AIM]; + SpeedStrain = values[ATTRIB_ID_SPEED]; + OverallDifficulty = values[ATTRIB_ID_OVERALL_DIFFICULTY]; + ApproachRate = values[ATTRIB_ID_APPROACH_RATE]; + MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; + StarRating = values[ATTRIB_ID_STRAIN]; + FlashlightRating = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT); + SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR]; + } + + // Used implicitly by Newtonsoft.Json to not serialize flashlight property in some cases. + [UsedImplicitly] + public bool ShouldSerializeFlashlightRating() => Mods.Any(m => m is ModFlashlight); } } diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs index 783636a62d..4bdb85ba60 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var controlPointInfo = new ControlPointInfo(); controlPointInfo.Add(0, new TimingControlPoint()); - WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap + IWorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { HitObjects = new List { new Hit { Type = HitType.Centre } }, BeatmapInfo = new BeatmapInfo diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index 36adbd5a5b..b2b5d056c3 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -1,16 +1,46 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Taiko.Difficulty { public class TaikoDifficultyAttributes : DifficultyAttributes { + [JsonProperty("stamina_strain")] public double StaminaStrain { get; set; } + + [JsonProperty("rhythm_strain")] public double RhythmStrain { get; set; } + + [JsonProperty("colour_strain")] public double ColourStrain { get; set; } + + [JsonProperty("approach_rate")] public double ApproachRate { get; set; } + + [JsonProperty("great_hit_window")] public double GreatHitWindow { get; set; } + + public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + { + foreach (var v in base.ToDatabaseAttributes()) + yield return v; + + yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); + yield return (ATTRIB_ID_STRAIN, StarRating); + yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); + } + + public override void FromDatabaseAttributes(IReadOnlyDictionary values) + { + base.FromDatabaseAttributes(values); + + MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; + StarRating = values[ATTRIB_ID_STRAIN]; + GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; + } } } diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index f03cda1489..1d8b754837 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Skins [Resolved] private BeatmapManager beatmaps { get; set; } - private WorkingBeatmap beatmap; + private IWorkingBeatmap beatmap; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index c758bd1707..eee0d6672c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -81,11 +81,11 @@ namespace osu.Game.Tests.Visual.Editing public class EditorBeatmapContainer : Container { - private readonly WorkingBeatmap working; + private readonly IWorkingBeatmap working; public EditorBeatmap EditorBeatmap { get; private set; } - public EditorBeatmapContainer(WorkingBeatmap working) + public EditorBeatmapContainer(IWorkingBeatmap working) { this.working = working; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs index c3a5a0e944..eb7e90f0a7 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneWaveform : OsuTestScene { - private WorkingBeatmap waveformBeatmap; + private IWorkingBeatmap waveformBeatmap; [BackgroundDependencyLoader] private void load(AudioManager audio) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index ba0ee5ac6e..06eaa726c9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -95,8 +95,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void prepareBeatmap() { - Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); - Beatmap.Value.BeatmapInfo.EpilepsyWarning = epilepsyWarning; + var workingBeatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning; + Beatmap.Value = workingBeatmap; foreach (var mod in SelectedMods.Value.OfType()) mod.ApplyToTrack(Beatmap.Value.Track); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 8f767659c6..7c2f1c5bb2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers { - private readonly WeakList workingWeakReferences = new WeakList(); + private readonly WeakList workingWeakReferences = new WeakList(); private readonly WeakList playerWeakReferences = new WeakList(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 5a2b8d22fd..3b6d02c67c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Gameplay track.Start(); } - private void loadStoryboard(WorkingBeatmap working) + private void loadStoryboard(IWorkingBeatmap working) { if (storyboard != null) storyboardContainer.Remove(storyboard); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 79dfe79299..6dda8df6f0 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Menus public void TestMusicNavigationActions() { int importId = 0; - Queue<(WorkingBeatmap working, TrackChangeDirection changeDirection)> trackChangeQueue = null; + Queue<(IWorkingBeatmap working, TrackChangeDirection changeDirection)> trackChangeQueue = null; // ensure we have at least two beatmaps available to identify the direction the music controller navigated to. AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(new BeatmapSetInfo @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("bind to track change", () => { - trackChangeQueue = new Queue<(WorkingBeatmap, TrackChangeDirection)>(); + trackChangeQueue = new Queue<(IWorkingBeatmap, TrackChangeDirection)>(); Game.MusicController.TrackChanged += (working, changeDirection) => trackChangeQueue.Enqueue((working, changeDirection)); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 8ac0a2cbe5..efc3b07d0a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -67,6 +67,19 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("no item selected", () => playlist.SelectedItem.Value == null); } + [Test] + public void TestMarkInvalid() + { + createPlaylist(true, true); + + AddStep("mark item 0 as invalid", () => playlist.Items[0].MarkInvalid()); + + moveToItem(0); + + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddAssert("no item selected", () => playlist.SelectedItem.Value == null); + } + [Test] public void TestSelectable() { diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs index ff976c7bf6..d1ee984682 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs @@ -7,6 +7,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Osu; @@ -139,7 +140,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("present beatmap", () => Game.PresentBeatmap(getImport())); AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect); - AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.ID == getImport().ID); + AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.MatchesOnlineID(getImport())); AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID); } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 5d4594c415..ef71c54e03 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Navigation Player player = null; ResultsScreen results = null; - WorkingBeatmap beatmap() => Game.Beatmap.Value; + IWorkingBeatmap beatmap() => Game.Beatmap.Value; PushAndConfirm(() => new TestPlaySongSelect()); @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.Navigation { Player player = null; - WorkingBeatmap beatmap() => Game.Beatmap.Value; + IWorkingBeatmap beatmap() => Game.Beatmap.Value; PushAndConfirm(() => new TestPlaySongSelect()); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 48222e6b94..278379c692 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.Playlists RoomManager.CreateRequested = r => { createdRoom = r; - return true; + return string.Empty; }; }); @@ -82,28 +82,58 @@ namespace osu.Game.Tests.Visual.Playlists AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration); } + [Test] + public void TestInvalidBeatmapError() + { + const string not_found_prefix = "beatmaps not found:"; + + string errorMesage = null; + + AddStep("setup", () => + { + var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo; + + SelectedRoom.Value.Name.Value = "Test Room"; + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = beatmap } }); + + errorMesage = $"{not_found_prefix} {beatmap.OnlineID}"; + + RoomManager.CreateRequested = _ => errorMesage; + }); + + AddAssert("error not displayed", () => !settings.ErrorText.IsPresent); + AddAssert("playlist item valid", () => SelectedRoom.Value.Playlist[0].Valid.Value); + + AddStep("create room", () => settings.ApplyButton.Action.Invoke()); + + AddAssert("error displayed", () => settings.ErrorText.IsPresent); + AddAssert("error has custom text", () => settings.ErrorText.Text != errorMesage); + AddAssert("playlist item marked invalid", () => !SelectedRoom.Value.Playlist[0].Valid.Value); + } + [Test] public void TestCreationFailureDisplaysError() { - bool fail; + const string error_message = "failed"; + + string failText = error_message; AddStep("setup", () => { SelectedRoom.Value.Name.Value = "Test Room"; SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); - fail = true; - RoomManager.CreateRequested = _ => !fail; + RoomManager.CreateRequested = _ => failText; }); AddAssert("error not displayed", () => !settings.ErrorText.IsPresent); AddStep("create room", () => settings.ApplyButton.Action.Invoke()); AddAssert("error displayed", () => settings.ErrorText.IsPresent); - AddAssert("error has correct text", () => settings.ErrorText.Text == TestRoomManager.FAILED_TEXT); + AddAssert("error has correct text", () => settings.ErrorText.Text == error_message); AddStep("create room no fail", () => { - fail = false; + failText = string.Empty; settings.ApplyButton.Action.Invoke(); }); @@ -132,9 +162,7 @@ namespace osu.Game.Tests.Visual.Playlists protected class TestRoomManager : IRoomManager { - public const string FAILED_TEXT = "failed"; - - public Func CreateRequested; + public Func CreateRequested; public event Action RoomsUpdated { @@ -157,8 +185,10 @@ namespace osu.Game.Tests.Visual.Playlists if (CreateRequested == null) return; - if (!CreateRequested.Invoke(room)) - onError?.Invoke(FAILED_TEXT); + string error = CreateRequested.Invoke(room); + + if (!string.IsNullOrEmpty(error)) + onError?.Invoke(error); else onSuccess?.Invoke(room); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index 9473b058cc..11d589f7bc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - private void showMetadataForBeatmap(Func getBeatmap) + private void showMetadataForBeatmap(Func getBeatmap) { AddStep("setup display", () => { diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index ee5a61f21f..0437c1b25b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -17,6 +17,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; @@ -360,7 +361,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo.Equals(target)); // this is an important check, to make sure updateComponentFromBeatmap() was actually run - AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.Equals(target)); + AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target)); } [Test] @@ -392,7 +393,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("has correct ruleset", () => Ruleset.Value.ID == 0); // this is an important check, to make sure updateComponentFromBeatmap() was actually run - AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.Equals(target)); + AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target)); } [Test] @@ -507,13 +508,13 @@ namespace osu.Game.Tests.Visual.SongSelect i.IsFiltered || i.Item.BeatmapInfo.Ruleset.ID == targetRuleset || i.Item.BeatmapInfo.Ruleset.ID == 0); }); - AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.OnlineID == target.OnlineID); - AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineID == target.OnlineID); + AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true); + AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(target)); AddStep("reset filter text", () => songSelect.FilterControl.ChildrenOfType().First().Text = string.Empty); - AddAssert("game still correct", () => Beatmap.Value?.BeatmapInfo.OnlineID == target.OnlineID); - AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmapInfo.OnlineID == target.OnlineID); + AddAssert("game still correct", () => Beatmap.Value?.BeatmapInfo.MatchesOnlineID(target) == true); + AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmapInfo.MatchesOnlineID(target)); } [Test] @@ -544,8 +545,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo != null); - AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.OnlineID == target.OnlineID); - AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineID == target.OnlineID); + AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true); + AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(target)); AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType().First().Text = "nononoo"); @@ -672,7 +673,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for selection", () => !Beatmap.IsDefault); - AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID); + AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID); AddAssert("selection changed once", () => changeCount == 1); AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0); @@ -683,8 +684,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("selection changed", () => changeCount > 1); - AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.ID == previousSetID); - AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3); + AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.OnlineID == previousSetID); + AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3); AddAssert("selection changed only fired twice", () => changeCount == 2); @@ -727,7 +728,7 @@ namespace osu.Game.Tests.Visual.SongSelect int previousSetID = 0; - AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID); + AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID); AddStep("Click on a difficulty", () => { @@ -738,8 +739,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3); - AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.ID == previousSetID); - AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3); + AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.OnlineID == previousSetID); + AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3); } [Test] @@ -784,7 +785,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3); - AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.Equals(groupIcon.Items.First().BeatmapInfo)); + AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(groupIcon.Items.First().BeatmapInfo)); } [Test] @@ -815,7 +816,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen()); - AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap())); + AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap())); AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0); } @@ -847,7 +848,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen()); - AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap())); + AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap())); AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0); } @@ -960,7 +961,7 @@ namespace osu.Game.Tests.Visual.SongSelect public new FilterControl FilterControl => base.FilterControl; public WorkingBeatmap CurrentBeatmap => Beatmap.Value; - public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; + public IWorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; public new BeatmapCarousel Carousel => base.Carousel; public new void PresentScore(ScoreInfo score) => base.PresentScore(score); diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index d761ea3212..5f20bf49b9 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -151,7 +151,7 @@ namespace osu.Game.Beatmaps }, cancellationToken, TaskCreationOptions.HideScheduler | TaskCreationOptions.RunContinuationsAsynchronously, updateScheduler); } - public Task> GetTimedDifficultyAttributesAsync(WorkingBeatmap beatmap, Ruleset ruleset, Mod[] mods, CancellationToken cancellationToken = default) + public Task> GetTimedDifficultyAttributesAsync(IWorkingBeatmap beatmap, Ruleset ruleset, Mod[] mods, CancellationToken cancellationToken = default) { return Task.Factory.StartNew(() => ruleset.CreateDifficultyCalculator(beatmap).CalculateTimed(mods, cancellationToken), cancellationToken, diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 48a6663adb..c2a2e93caf 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -179,7 +179,7 @@ namespace osu.Game.Beatmaps /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// - public WorkingBeatmap DefaultBeatmap => workingBeatmapCache.DefaultBeatmap; + public IWorkingBeatmap DefaultBeatmap => workingBeatmapCache.DefaultBeatmap; /// /// Fired when a notification should be presented to the user. diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index 0c59eec1ef..916df429a4 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -9,9 +9,9 @@ namespace osu.Game.Beatmaps.Drawables { public class BeatmapBackgroundSprite : Sprite { - private readonly WorkingBeatmap working; + private readonly IWorkingBeatmap working; - public BeatmapBackgroundSprite(WorkingBeatmap working) + public BeatmapBackgroundSprite(IWorkingBeatmap working) { if (working == null) throw new ArgumentNullException(nameof(working)); diff --git a/osu.Game/Online/Chat/NowPlayingCommand.cs b/osu.Game/Online/Chat/NowPlayingCommand.cs index 34b12c23e6..2bf35d7973 100644 --- a/osu.Game/Online/Chat/NowPlayingCommand.cs +++ b/osu.Game/Online/Chat/NowPlayingCommand.cs @@ -37,7 +37,7 @@ namespace osu.Game.Online.Chat base.LoadComplete(); string verb; - BeatmapInfo beatmapInfo; + IBeatmapInfo beatmapInfo; switch (api.Activity.Value) { @@ -57,7 +57,7 @@ namespace osu.Game.Online.Chat break; } - string beatmapString = beatmapInfo.OnlineID.HasValue ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString(); + string beatmapString = beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString(); channelManager.PostMessage($"is {verb} {beatmapString}", true, target); Expire(); diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 6f3d13b224..2de1bf9d89 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -30,6 +30,11 @@ namespace osu.Game.Online.Rooms [JsonProperty("expired")] public bool Expired { get; set; } + [JsonIgnore] + public IBindable Valid => valid; + + private readonly Bindable valid = new BindableBool(true); + [JsonIgnore] public readonly Bindable Beatmap = new Bindable(); @@ -69,6 +74,8 @@ namespace osu.Game.Online.Rooms Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.OnlineID ?? 0); } + public void MarkInvalid() => valid.Value = false; + public void MapObjects(RulesetStore rulesets) { Beatmap.Value ??= apiBeatmap; diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index 6bb780a68b..e0d27799ce 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -1,28 +1,87 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Difficulty { + /// + /// Describes the difficulty of a beatmap, as output by a . + /// + [JsonObject(MemberSerialization.OptIn)] public class DifficultyAttributes { + protected const int ATTRIB_ID_AIM = 1; + protected const int ATTRIB_ID_SPEED = 3; + protected const int ATTRIB_ID_OVERALL_DIFFICULTY = 5; + protected const int ATTRIB_ID_APPROACH_RATE = 7; + protected const int ATTRIB_ID_MAX_COMBO = 9; + protected const int ATTRIB_ID_STRAIN = 11; + protected const int ATTRIB_ID_GREAT_HIT_WINDOW = 13; + protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15; + protected const int ATTRIB_ID_FLASHLIGHT = 17; + protected const int ATTRIB_ID_SLIDER_FACTOR = 19; + + /// + /// The mods which were applied to the beatmap. + /// public Mod[] Mods { get; set; } + + /// + /// The skills resulting from the difficulty calculation. + /// public Skill[] Skills { get; set; } + /// + /// The combined star rating of all skill. + /// + [JsonProperty("star_rating", Order = -3)] public double StarRating { get; set; } + + /// + /// The maximum achievable combo. + /// + [JsonProperty("max_combo", Order = -2)] public int MaxCombo { get; set; } + /// + /// Creates new . + /// public DifficultyAttributes() { } + /// + /// Creates new . + /// + /// The mods which were applied to the beatmap. + /// The skills resulting from the difficulty calculation. + /// The combined star rating of all skills. public DifficultyAttributes(Mod[] mods, Skill[] skills, double starRating) { Mods = mods; Skills = skills; StarRating = starRating; } + + /// + /// Converts this to osu-web compatible database attribute mappings. + /// + /// + /// See: osu_difficulty_attribs table. + /// + public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() => Enumerable.Empty<(int, object)>(); + + /// + /// Reads osu-web database attribute mappings into this object. + /// + /// The attribute mappings. + public virtual void FromDatabaseAttributes(IReadOnlyDictionary values) + { + } } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 817fb07d4b..96ff44fab5 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; -using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; @@ -45,6 +44,8 @@ namespace osu.Game.Screens.OnlinePlay private ExplicitContentBeatmapPill explicitContentPill; private ModDisplay modDisplay; + private readonly IBindable valid = new Bindable(); + private readonly Bindable beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); private readonly BindableList requiredMods = new BindableList(); @@ -66,14 +67,18 @@ namespace osu.Game.Screens.OnlinePlay this.allowSelection = allowSelection; beatmap.BindTo(item.Beatmap); + valid.BindTo(item.Valid); ruleset.BindTo(item.Ruleset); requiredMods.BindTo(item.RequiredMods); ShowDragHandle.Value = allowEdit; } + [Resolved] + private OsuColour colours { get; set; } + [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { if (!allowEdit) HandleColour = HandleColour.Opacity(0); @@ -85,27 +90,43 @@ namespace osu.Game.Screens.OnlinePlay { base.LoadComplete(); - SelectedItem.BindValueChanged(selected => maskingContainer.BorderThickness = selected.NewValue == Model ? 5 : 0, true); + SelectedItem.BindValueChanged(selected => + { + bool isCurrent = selected.NewValue == Model; - beatmap.BindValueChanged(_ => scheduleRefresh()); - ruleset.BindValueChanged(_ => scheduleRefresh()); + if (!valid.Value) + { + // Don't allow selection when not valid. + if (isCurrent) + { + SelectedItem.Value = selected.OldValue; + } - requiredMods.CollectionChanged += (_, __) => scheduleRefresh(); + // Don't update border when not valid (the border is displaying this fact). + return; + } + + maskingContainer.BorderThickness = isCurrent ? 5 : 0; + }, true); + + beatmap.BindValueChanged(_ => Scheduler.AddOnce(refresh)); + ruleset.BindValueChanged(_ => Scheduler.AddOnce(refresh)); + valid.BindValueChanged(_ => Scheduler.AddOnce(refresh)); + requiredMods.CollectionChanged += (_, __) => Scheduler.AddOnce(refresh); refresh(); } - private ScheduledDelegate scheduledRefresh; private PanelBackground panelBackground; - private void scheduleRefresh() - { - scheduledRefresh?.Cancel(); - scheduledRefresh = Schedule(refresh); - } - private void refresh() { + if (!valid.Value) + { + maskingContainer.BorderThickness = 5; + maskingContainer.BorderColour = colours.Red; + } + difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; panelBackground.Beatmap.Value = Item.Beatmap.Value; @@ -278,7 +299,7 @@ namespace osu.Game.Screens.OnlinePlay protected override bool OnClick(ClickEvent e) { - if (allowSelection) + if (allowSelection && valid.Value) SelectedItem.Value = Model; return true; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index c2bd7730e9..27c8dc1120 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Specialized; +using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -204,7 +205,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { new Drawable[] { - playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both } + playlist = new DrawableRoomPlaylist(true, false) { RelativeSizeAxes = Axes.Both } }, new Drawable[] { @@ -339,9 +340,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(room, onSuccess, onError); - loadingLayer.Show(); + manager?.CreateRoom(room, onSuccess, onError); } private void hideError() => ErrorText.FadeOut(50); @@ -350,9 +350,31 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private void onError(string text) { - ErrorText.Text = text; - ErrorText.FadeIn(50); + // see https://github.com/ppy/osu-web/blob/2c97aaeb64fb4ed97c747d8383a35b30f57428c7/app/Models/Multiplayer/PlaylistItem.php#L48. + const string not_found_prefix = "beatmaps not found:"; + if (text.StartsWith(not_found_prefix, StringComparison.Ordinal)) + { + ErrorText.Text = "One or more beatmaps were not available online. Please remove or replace the highlighted items."; + + int[] invalidBeatmapIDs = text + .Substring(not_found_prefix.Length + 1) + .Split(", ") + .Select(int.Parse) + .ToArray(); + + foreach (var item in Playlist) + { + if (invalidBeatmapIDs.Contains(item.BeatmapID)) + item.MarkInvalid(); + } + } + else + { + ErrorText.Text = text; + } + + ErrorText.FadeIn(50); loadingLayer.Hide(); } } diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 430571e1da..795dddfaf5 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play /// public class BeatmapMetadataDisplay : Container { - private readonly WorkingBeatmap beatmap; + private readonly IWorkingBeatmap beatmap; private readonly Bindable> mods; private readonly Drawable logoFacade; private LoadingSpinner loading; @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play } } - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable logoFacade) + public BeatmapMetadataDisplay(IWorkingBeatmap beatmap, Bindable> mods, Drawable logoFacade) { this.beatmap = beatmap; this.logoFacade = logoFacade; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1381493fdf..4d574dea99 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -354,7 +354,7 @@ namespace osu.Game.Screens.Play private Drawable createUnderlayComponents() => DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }; - private Drawable createGameplayComponents(WorkingBeatmap working, IBeatmap playableBeatmap) => new ScalingContainer(ScalingMode.Gameplay) + private Drawable createGameplayComponents(IWorkingBeatmap working, IBeatmap playableBeatmap) => new ScalingContainer(ScalingMode.Gameplay) { Children = new Drawable[] { @@ -372,7 +372,7 @@ namespace osu.Game.Screens.Play } }; - private Drawable createOverlayComponents(WorkingBeatmap working) + private Drawable createOverlayComponents(IWorkingBeatmap working) { var container = new Container { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index 25056790cc..d9b8a20846 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs @@ -15,9 +15,9 @@ namespace osu.Game.Screens.Select { internal class BeatmapInfoWedgeBackground : CompositeDrawable { - private readonly WorkingBeatmap beatmap; + private readonly IWorkingBeatmap beatmap; - public BeatmapInfoWedgeBackground(WorkingBeatmap beatmap) + public BeatmapInfoWedgeBackground(IWorkingBeatmap beatmap) { this.beatmap = beatmap; } diff --git a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs index b4279cce51..2a37969be1 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Select.Carousel { public class SetPanelBackground : BufferedContainer { - public SetPanelBackground(WorkingBeatmap working) + public SetPanelBackground(IWorkingBeatmap working) : base(cachedFrameBuffer: true) { RedrawOnScale = false; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4da15ee53c..aef00a9b00 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -671,7 +671,7 @@ namespace osu.Game.Screens.Select music.TrackChanged -= ensureTrackLooping; } - private void ensureTrackLooping(WorkingBeatmap beatmap, TrackChangeDirection changeDirection) + private void ensureTrackLooping(IWorkingBeatmap beatmap, TrackChangeDirection changeDirection) => beatmap.PrepareTrackForPreviewLooping(); public override bool OnBackButton() diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 9e3d3df915..d3d6797eae 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -89,7 +89,7 @@ namespace osu.Game.Storyboards } } - public DrawableStoryboard CreateDrawable(WorkingBeatmap working = null) => + public DrawableStoryboard CreateDrawable(IWorkingBeatmap working = null) => new DrawableStoryboard(this); public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 91bcb37fcc..0874685f49 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -27,11 +27,11 @@ namespace osu.Game.Users public abstract class InGame : UserActivity { - public BeatmapInfo BeatmapInfo { get; } + public IBeatmapInfo BeatmapInfo { get; } public RulesetInfo Ruleset { get; } - protected InGame(BeatmapInfo beatmapInfo, RulesetInfo ruleset) + protected InGame(IBeatmapInfo beatmapInfo, RulesetInfo ruleset) { BeatmapInfo = beatmapInfo; Ruleset = ruleset; @@ -42,7 +42,7 @@ namespace osu.Game.Users public class InMultiplayerGame : InGame { - public InMultiplayerGame(BeatmapInfo beatmapInfo, RulesetInfo ruleset) + public InMultiplayerGame(IBeatmapInfo beatmapInfo, RulesetInfo ruleset) : base(beatmapInfo, ruleset) { } @@ -52,7 +52,7 @@ namespace osu.Game.Users public class InPlaylistGame : InGame { - public InPlaylistGame(BeatmapInfo beatmapInfo, RulesetInfo ruleset) + public InPlaylistGame(IBeatmapInfo beatmapInfo, RulesetInfo ruleset) : base(beatmapInfo, ruleset) { } @@ -60,7 +60,7 @@ namespace osu.Game.Users public class InSoloGame : InGame { - public InSoloGame(BeatmapInfo beatmapInfo, RulesetInfo ruleset) + public InSoloGame(IBeatmapInfo beatmapInfo, RulesetInfo ruleset) : base(beatmapInfo, ruleset) { } @@ -68,9 +68,9 @@ namespace osu.Game.Users public class Editing : UserActivity { - public BeatmapInfo BeatmapInfo { get; } + public IBeatmapInfo BeatmapInfo { get; } - public Editing(BeatmapInfo info) + public Editing(IBeatmapInfo info) { BeatmapInfo = info; }