From 4dab5db2e5fd7baefece1385edf13b6907845f93 Mon Sep 17 00:00:00 2001 From: Scotsoo Date: Tue, 13 Nov 2018 17:09:28 +0000 Subject: [PATCH 01/76] Allowing keypad enter to be used along with normal enter --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 2f5f1aea3f..c58e845a6a 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -43,6 +43,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Space, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select), + new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), }; public IEnumerable InGameKeyBindings => new[] From d5464702fa16113c62d95ca2ee2f0b96021f7291 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 20:56:34 +0900 Subject: [PATCH 02/76] Fix post-merge issue --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b42758ebad..d41fd5c201 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Edit /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// - public virtual bool CursorInPlacementArea => rulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public virtual bool CursorInPlacementArea => RulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); /// /// Adds a to the and visualises it. From df7515b66ffb5854024c909a9e81da733d9d79bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 21:01:06 +0900 Subject: [PATCH 03/76] Pass all selected hitobjects to the selection blueprints --- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 3 ++- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 3 ++- .../Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs | 4 +++- .../Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs | 4 +++- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 ++- osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 43e359cf2c..d47f43fb06 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - public override void AdjustPosition(DragEvent dragEvent) + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { var objectParent = HitObject.Parent; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 8431d5d5d0..e0dd1430fe 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; @@ -17,6 +18,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints { } - public override void AdjustPosition(DragEvent dragEvent) => OsuObject.Position += dragEvent.Delta; + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => OsuObject.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index 4bac9d3556..aa33d4c89a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -25,6 +27,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. public override bool HandlePositionalInput => false; - public override void AdjustPosition(DragEvent dragEvent) => slider.Position += dragEvent.Delta; + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => slider.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index 9e9cc87c5e..f8f632535d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -21,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); - public override void AdjustPosition(DragEvent dragEvent) + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { // Spinners don't support position adjustments } diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index db35d47b2b..c9d6719a92 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -134,7 +135,7 @@ namespace osu.Game.Rulesets.Edit return true; } - public abstract void AdjustPosition(DragEvent dragEvent); + public abstract void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects); /// /// The screen-space point that causes this to be selected. diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 8732672723..5d334ca559 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // Todo: Various forms of snapping foreach (var blueprint in selectedBlueprints) - blueprint.AdjustPosition(dragEvent); + blueprint.AdjustPosition(dragEvent, selectedBlueprints.Select(b => b.HitObject)); } protected override bool OnKeyDown(KeyDownEvent e) From f7fc2ca5697bc362b5ffceeca8de3bd58a0fea10 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 21:37:22 +0900 Subject: [PATCH 04/76] Basic inter-column selection movement --- .../ManiaPlacementBlueprintTestCase.cs | 2 + .../ManiaSelectionBlueprintTestCase.cs | 25 ++++++++++++- .../Blueprints/ManiaSelectionBlueprint.cs | 37 +++++++++++++++++++ .../Edit/IManiaHitObjectComposer.cs | 2 + .../Edit/ManiaHitObjectComposer.cs | 2 + .../Objects/ManiaHitObject.cs | 9 ++++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 +++ osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 14 ++++++- 8 files changed, 93 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs index 0c87978f15..6162d6844f 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -46,5 +46,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override void AddHitObject(DrawableHitObject hitObject) => column.Add((DrawableManiaHitObject)hitObject); public Column ColumnAt(Vector2 screenSpacePosition) => column; + + public int TotalColumns => 1; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs index 8c5299e1a2..f64e54c878 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs @@ -2,14 +2,37 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { - public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase + [Cached(Type = typeof(IManiaHitObjectComposer))] + public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase, IManiaHitObjectComposer { [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); + + private readonly Column column; + + protected ManiaSelectionBlueprintTestCase() + { + Add(column = new Column(0) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.OrangeRed, + Clock = new FramedClock(new StopwatchClock()), // No scroll + }); + } + + public Column ColumnAt(Vector2 screenSpacePosition) => column; + + public int TotalColumns => 1; } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index d47f43fb06..ea2642ef29 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -2,11 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -20,6 +24,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + public ManiaSelectionBlueprint(DrawableHitObject hitObject) : base(hitObject) { @@ -41,6 +48,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { + var maniaObject = (ManiaHitObject)HitObject.HitObject; + var objectParent = HitObject.Parent; // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame @@ -60,6 +69,34 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints EditorClock.CurrentTime, scrollingInfo.TimeRange.Value, objectParent.DrawHeight); + + var lastColumn = ColumnAt(dragEvent.ScreenSpaceLastMousePosition); + var currentColumn = ColumnAt(dragEvent.ScreenSpaceMousePosition); + if (lastColumn != null && currentColumn != null) + { + int columnDelta = currentColumn.Index - lastColumn.Index; + + if (columnDelta != 0) + { + int minColumn = int.MaxValue; + int maxColumn = int.MinValue; + + foreach (var obj in selectedObjects.OfType()) + { + if (obj.HitObject.Column < minColumn) + minColumn = obj.HitObject.Column; + if (obj.HitObject.Column > maxColumn) + maxColumn = obj.HitObject.Column; + } + + columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + } + + Schedule(() => maniaObject.Column += columnDelta); + } } + + protected Column ColumnAt(Vector2 screenSpacePosition) => composer.ColumnAt(screenSpacePosition); + } } diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index 6347370d72..5b577ce2fe 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -9,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Edit public interface IManiaHitObjectComposer { Column ColumnAt(Vector2 screenSpacePosition); + + int TotalColumns { get; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 07684f9eb8..01d360adfe 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -31,6 +31,8 @@ namespace osu.Game.Rulesets.Mania.Edit public Column ColumnAt(Vector2 screenSpacePosition) => ((ManiaPlayfield)RulesetContainer.Playfield).GetColumnByPosition(screenSpacePosition); + public int TotalColumns => ((ManiaPlayfield)RulesetContainer.Playfield).TotalColumns; + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) { var rulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index e183098a51..bb3d060e61 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Configuration; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -8,7 +9,13 @@ namespace osu.Game.Rulesets.Mania.Objects { public abstract class ManiaHitObject : HitObject, IHasColumn { - public virtual int Column { get; set; } + public readonly Bindable ColumnBindable = new Bindable(); + + public virtual int Column + { + get => ColumnBindable; + set => ColumnBindable.Value = value; + } protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 410c6aa908..f4ea02f7e4 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -81,6 +82,11 @@ namespace osu.Game.Rulesets.Mania.UI return found; } + /// + /// Retrieves the total amount of columns across all stages in this playfield. + /// + public int TotalColumns => stages.Sum(s => s.Columns.Count); + private ManiaStage getStageByColumn(int column) { int sum = 0; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index d1ce8b8679..2730159828 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -152,8 +152,18 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject h) { var maniaObject = (ManiaHitObject)h.HitObject; - int columnIndex = maniaObject.Column - firstColumnIndex; - Columns.ElementAt(columnIndex).Add(h); + + int columnIndex = -1; + + maniaObject.ColumnBindable.BindValueChanged(_ => + { + if (columnIndex != -1) + Columns.ElementAt(columnIndex).Remove(h); + + columnIndex = maniaObject.Column - firstColumnIndex; + Columns.ElementAt(columnIndex).Add(h); + }, true); + h.OnNewResult += OnNewResult; } From 4cbda97b1eebc9ff140a6a617bb3dab821c9ec24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 16 Nov 2018 17:12:24 +0900 Subject: [PATCH 05/76] Move positional adjustment to SelectionBox --- .../Blueprints/ManiaSelectionBlueprint.cs | 59 ------------ .../Edit/ManiaHitObjectComposer.cs | 3 + .../Edit/ManiaSelectionBox.cs | 89 +++++++++++++++++++ .../Edit/Blueprints/OsuSelectionBlueprint.cs | 4 - .../Sliders/SliderCircleSelectionBlueprint.cs | 9 -- .../Spinners/SpinnerSelectionBlueprint.cs | 8 -- .../Edit/OsuHitObjectComposer.cs | 3 + osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs | 29 ++++++ osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 - .../Edit/Compose/Components/SelectionBox.cs | 18 ++-- 10 files changed, 133 insertions(+), 92 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index ea2642ef29..05909b717f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,16 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -45,58 +39,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) - { - var maniaObject = (ManiaHitObject)HitObject.HitObject; - - var objectParent = HitObject.Parent; - - // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame - // without the position having been updated by the parenting ScrollingHitObjectContainer - HitObject.Y += dragEvent.Delta.Y; - - float targetPosition; - - // If we're scrolling downwards, a position of 0 is actually further away from the hit target - // so we need to flip the vertical coordinate in the hitobject container's space - if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - targetPosition = -HitObject.Position.Y; - else - targetPosition = HitObject.Position.Y; - - HitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, - EditorClock.CurrentTime, - scrollingInfo.TimeRange.Value, - objectParent.DrawHeight); - - var lastColumn = ColumnAt(dragEvent.ScreenSpaceLastMousePosition); - var currentColumn = ColumnAt(dragEvent.ScreenSpaceMousePosition); - if (lastColumn != null && currentColumn != null) - { - int columnDelta = currentColumn.Index - lastColumn.Index; - - if (columnDelta != 0) - { - int minColumn = int.MaxValue; - int maxColumn = int.MinValue; - - foreach (var obj in selectedObjects.OfType()) - { - if (obj.HitObject.Column < minColumn) - minColumn = obj.HitObject.Column; - if (obj.HitObject.Column > maxColumn) - maxColumn = obj.HitObject.Column; - } - - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); - } - - Schedule(() => maniaObject.Column += columnDelta); - } - } - - protected Column ColumnAt(Vector2 screenSpacePosition) => composer.ColumnAt(screenSpacePosition); - } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 01d360adfe..eca70a03d4 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -12,6 +12,7 @@ using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Compose.Components; using OpenTK; namespace osu.Game.Rulesets.Mania.Edit @@ -48,6 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit new NoteCompositionTool() }; + public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox(); + public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { switch (hitObject) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs new file mode 100644 index 0000000000..83a04639eb --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs @@ -0,0 +1,89 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Input.Events; +using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit.Compose.Components; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaSelectionBox : SelectionBox + { + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + + private IClock editorClock; + + [BackgroundDependencyLoader] + private void load(IAdjustableClock clock) + { + editorClock = clock; + } + + public override void HandleDrag(DragEvent dragEvent) + { + foreach (var blueprint in SelectedBlueprints) + { + var hitObject = blueprint.HitObject; + + var objectParent = hitObject.Parent; + + // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame + // without the position having been updated by the parenting ScrollingHitObjectContainer + hitObject.Y += dragEvent.Delta.Y; + + float targetPosition; + + // If we're scrolling downwards, a position of 0 is actually further away from the hit target + // so we need to flip the vertical coordinate in the hitobject container's space + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + targetPosition = -hitObject.Position.Y; + else + targetPosition = hitObject.Position.Y; + + hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, + editorClock.CurrentTime, + scrollingInfo.TimeRange.Value, + objectParent.DrawHeight); + } + + adjustColumn(dragEvent); + } + + private void adjustColumn(DragEvent dragEvent) + { + var lastColumn = composer.ColumnAt(dragEvent.ScreenSpaceLastMousePosition); + var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceMousePosition); + if (lastColumn == null || currentColumn == null) + return; + + int columnDelta = currentColumn.Index - lastColumn.Index; + if (columnDelta == 0) + return; + + int minColumn = int.MaxValue; + int maxColumn = int.MinValue; + + foreach (var obj in SelectedHitObjects.OfType()) + { + if (obj.Column < minColumn) + minColumn = obj.Column; + if (obj.Column > maxColumn) + maxColumn = obj.Column; + } + + columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + + foreach (var obj in SelectedHitObjects.OfType()) + obj.Column += columnDelta; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index e0dd1430fe..fab9c27c6d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -17,7 +15,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints : base(hitObject) { } - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => OsuObject.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index aa33d4c89a..32258572bf 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,9 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -12,13 +9,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint { - private readonly Slider slider; - public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position) : base(hitObject) { - this.slider = slider; - InternalChild = new SliderCirclePiece(slider, position); Select(); @@ -26,7 +19,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. public override bool HandlePositionalInput => false; - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => slider.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index f8f632535d..eefdc7e214 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,9 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -22,10 +19,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) - { - // Spinners don't support position adjustments - } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a706e1d4be..0d50f27016 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { @@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; + public override SelectionBox CreateSelectionBox() => new OsuSelectionBox(); + protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs new file mode 100644 index 0000000000..ca7d26e879 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuSelectionBox : SelectionBox + { + public override void HandleDrag(DragEvent dragEvent) + { + base.HandleDrag(dragEvent); + + foreach (var h in SelectedHitObjects.OfType()) + { + if (h is Spinner) + { + // Spinners don't support position adjustments + continue; + } + + h.Position += dragEvent.Delta; + } + } + } +} diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index c9d6719a92..c27f0929c6 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -135,8 +134,6 @@ namespace osu.Game.Rulesets.Edit return true; } - public abstract void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects); - /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 5d334ca559..b2d692bd39 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -12,6 +12,7 @@ using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; using OpenTK; using OpenTK.Input; @@ -24,8 +25,11 @@ namespace osu.Game.Screens.Edit.Compose.Components { public const float BORDER_RADIUS = 2; + protected IEnumerable SelectedBlueprints => selectedBlueprints; private readonly List selectedBlueprints; + protected IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject); + private Drawable outline; [Resolved] @@ -59,12 +63,8 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling - public void HandleDrag(DragEvent dragEvent) + public virtual void HandleDrag(DragEvent dragEvent) { - // Todo: Various forms of snapping - - foreach (var blueprint in selectedBlueprints) - blueprint.AdjustPosition(dragEvent, selectedBlueprints.Select(b => b.HitObject)); } protected override bool OnKeyDown(KeyDownEvent e) @@ -90,19 +90,19 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Bind an action to deselect all selected blueprints. /// - public Action DeselectAll { private get; set; } + internal Action DeselectAll { private get; set; } /// /// Handle a blueprint becoming selected. /// /// The blueprint. - public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint); + internal void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint); /// /// Handle a blueprint becoming deselected. /// /// The blueprint. - public void HandleDeselected(SelectionBlueprint blueprint) + internal void HandleDeselected(SelectionBlueprint blueprint) { selectedBlueprints.Remove(blueprint); @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Handle a blueprint requesting selection. /// /// The blueprint. - public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) + internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) { if (state.Keyboard.ControlPressed) { From ce956d7fd41feb9ca9e3a3201bad7834756302dd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:19:56 +0900 Subject: [PATCH 06/76] Fix exception when order of objects changes --- osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs index 83a04639eb..9dd0d617c4 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; using OpenTK; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Edit { var hitObject = blueprint.HitObject; - var objectParent = hitObject.Parent; + var objectParent = (HitObjectContainer)hitObject.Parent; // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame // without the position having been updated by the parenting ScrollingHitObjectContainer @@ -49,10 +50,14 @@ namespace osu.Game.Rulesets.Mania.Edit else targetPosition = hitObject.Position.Y; + objectParent.Remove(hitObject); + hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, editorClock.CurrentTime, scrollingInfo.TimeRange.Value, objectParent.DrawHeight); + + objectParent.Add(hitObject); } adjustColumn(dragEvent); From 595e2ffbffba517f949da656d84346884a59f305 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:20:21 +0900 Subject: [PATCH 07/76] Unbind event when column changes --- osu.Game.Rulesets.Mania/UI/Column.cs | 9 +++++++++ osu.Game/Rulesets/UI/Playfield.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 4c1929f182..45b8ab2b00 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -145,6 +145,15 @@ namespace osu.Game.Rulesets.Mania.UI HitObjectContainer.Add(hitObject); } + public override bool Remove(DrawableHitObject h) + { + if (!base.Remove(h)) + return false; + + h.OnNewResult -= OnNewResult; + return true; + } + internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 886eb3ac0e..76045bb650 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.UI /// Remove a DrawableHitObject from this Playfield. /// /// The DrawableHitObject to remove. - public virtual void Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); + public virtual bool Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); /// /// Registers a as a nested . From 55edeb095d2e276fa14074029081e9ddce04e0b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:58:11 +0900 Subject: [PATCH 08/76] SelectionBox -> SelectionHandler --- .../Edit/ManiaHitObjectComposer.cs | 2 +- ...electionBox.cs => ManiaSelectionHandler.cs} | 2 +- .../Edit/OsuHitObjectComposer.cs | 2 +- ...uSelectionBox.cs => OsuSelectionHandler.cs} | 2 +- .../Visual/TestCaseHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 ++--- .../Compose/Components/BlueprintContainer.cs | 18 +++++++++--------- .../Screens/Edit/Compose/Components/DragBox.cs | 2 +- .../{SelectionBox.cs => SelectionHandler.cs} | 12 ++++++++---- 9 files changed, 25 insertions(+), 22 deletions(-) rename osu.Game.Rulesets.Mania/Edit/{ManiaSelectionBox.cs => ManiaSelectionHandler.cs} (98%) rename osu.Game.Rulesets.Osu/Edit/{OsuSelectionBox.cs => OsuSelectionHandler.cs} (93%) rename osu.Game/Screens/Edit/Compose/Components/{SelectionBox.cs => SelectionHandler.cs} (91%) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index eca70a03d4..e6eb1c9f0e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Edit new NoteCompositionTool() }; - public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox(); + public override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler(); public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs similarity index 98% rename from osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs rename to osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9dd0d617c4..944e634c9c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -13,7 +13,7 @@ using OpenTK; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaSelectionBox : SelectionBox + public class ManiaSelectionHandler : SelectionHandler { [Resolved] private IScrollingInfo scrollingInfo { get; set; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 0d50f27016..117af9e853 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; - public override SelectionBox CreateSelectionBox() => new OsuSelectionBox(); + public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs similarity index 93% rename from osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs rename to osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index ca7d26e879..54f629cbea 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuSelectionBox : SelectionBox + public class OsuSelectionHandler : SelectionHandler { public override void HandleDrag(DragEvent dragEvent) { diff --git a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs index d894d2738e..d0eb63bf57 100644 --- a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { - typeof(SelectionBox), + typeof(SelectionHandler), typeof(DragBox), typeof(HitObjectComposer), typeof(OsuHitObjectComposer), diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index d41fd5c201..da7c3dda6a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -171,10 +171,9 @@ namespace osu.Game.Rulesets.Edit public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; /// - /// Creates a which outlines s - /// and handles hitobject pattern adjustments. + /// Creates a which outlines s and handles movement of selections. /// - public virtual SelectionBox CreateSelectionBox() => new SelectionBox(); + public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); /// /// Creates a which provides a layer above or below the . diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 1623ef0100..4664d521ec 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private Container placementBlueprintContainer; private PlacementBlueprint currentPlacement; - private SelectionBox selectionBox; + private SelectionHandler selectionHandler; private IEnumerable selections => selectionBlueprints.Children.Where(c => c.IsAlive); @@ -37,16 +37,16 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - selectionBox = composer.CreateSelectionBox(); - selectionBox.DeselectAll = deselectAll; + selectionHandler = composer.CreateSelectionHandler(); + selectionHandler.DeselectAll = deselectAll; var dragBox = new DragBox(select); - dragBox.DragEnd += () => selectionBox.UpdateVisibility(); + dragBox.DragEnd += () => selectionHandler.UpdateVisibility(); InternalChildren = new[] { dragBox, - selectionBox, + selectionHandler, selectionBlueprints = new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both }, placementBlueprintContainer = new Container { RelativeSizeAxes = Axes.Both }, dragBox.CreateProxy() @@ -168,19 +168,19 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onBlueprintSelected(SelectionBlueprint blueprint) { - selectionBox.HandleSelected(blueprint); + selectionHandler.HandleSelected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 1); } private void onBlueprintDeselected(SelectionBlueprint blueprint) { - selectionBox.HandleDeselected(blueprint); + selectionHandler.HandleDeselected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 0); } - private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionBox.HandleSelectionRequested(blueprint, state); + private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private void onDragRequested(DragEvent dragEvent) => selectionBox.HandleDrag(dragEvent); + private void onDragRequested(DragEvent dragEvent) => selectionHandler.HandleDrag(dragEvent); private class SelectionBlueprintContainer : Container { diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 1a58f476ac..0e1c9c7304 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { Masking = true, BorderColour = Color4.White, - BorderThickness = SelectionBox.BORDER_RADIUS, + BorderThickness = SelectionHandler.BORDER_RADIUS, Child = new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs similarity index 91% rename from osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs rename to osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index b2d692bd39..46c303df35 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -19,9 +19,9 @@ using OpenTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { /// - /// A box which surrounds s and provides interactive handles, context menus etc. + /// A component which outlines s and handles movement of selections. /// - public class SelectionBox : CompositeDrawable + public class SelectionHandler : CompositeDrawable { public const float BORDER_RADIUS = 2; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private IPlacementHandler placementHandler { get; set; } - public SelectionBox() + public SelectionHandler() { selectedBlueprints = new List(); @@ -63,6 +63,10 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling + /// + /// Handles the selected s being dragged. + /// + /// The drag event. public virtual void HandleDrag(DragEvent dragEvent) { } @@ -139,7 +143,7 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion /// - /// Updates whether this is visible. + /// Updates whether this is visible. /// internal void UpdateVisibility() { From 60ffad169fc1c1984537aff5f4eb5963728254a3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 11:47:48 +0900 Subject: [PATCH 09/76] Fix post-merge errors --- .../ManiaSelectionBlueprintTestCase.cs | 4 ++-- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs index f64e54c878..50de5ce7a3 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs @@ -7,8 +7,8 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; -using OpenTK; -using OpenTK.Graphics; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 6752378dfd..fc0180069d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - } public override void Show() { @@ -54,5 +53,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { HitObject.AlwaysAlive = false; base.Hide(); + } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 944e634c9c..4cb417a32e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.Edit { From f9f300b215d07f3859bc32f73f6ad2981e0f1f33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 16:08:56 +0900 Subject: [PATCH 10/76] Fix drag breaking if scrolling while dragging --- .../Blueprints/ManiaSelectionBlueprint.cs | 22 ++++++++++ .../Edit/ManiaSelectionHandler.cs | 43 ++++++++++++++++--- .../Edit/OsuSelectionHandler.cs | 7 +-- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 4 +- .../Compose/Components/BlueprintContainer.cs | 2 +- .../Compose/Components/SelectionHandler.cs | 4 +- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index fc0180069d..df229b23ae 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -14,6 +15,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class ManiaSelectionBlueprint : SelectionBlueprint { + public Vector2 ScreenSpaceMouseDownPosition { get; private set; } + public Vector2 MouseDownPosition { get; private set; } + protected new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; protected IClock EditorClock { get; private set; } @@ -43,6 +47,24 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } + protected override bool OnMouseDown(MouseDownEvent e) + { + ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; + MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + + return base.OnMouseDown(e); + } + + protected override bool OnDrag(DragEvent e) + { + var result = base.OnDrag(e); + + ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; + MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + + return result; + } + public override void Show() { HitObject.AlwaysAlive = true; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 4cb417a32e..1d6b9d6c69 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -5,6 +5,8 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Timing; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -29,11 +31,42 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleDrag(DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { - foreach (var blueprint in SelectedBlueprints) + adjustOrigins((ManiaSelectionBlueprint)blueprint); + performDragMovement(dragEvent); + performColumnMovement(dragEvent); + + base.HandleDrag(blueprint, dragEvent); + } + + /// + /// Ensures that the position of hitobjects remains centred to the mouse position. + /// E.g. The hitobject position will change if the editor scrolls while a hitobject is dragged. + /// + /// The that received the drag event. + private void adjustOrigins(ManiaSelectionBlueprint reference) + { + var referenceParent = (HitObjectContainer)reference.HitObject.Parent; + + float offsetFromReferenceOrigin = reference.MouseDownPosition.Y - reference.HitObject.OriginPosition.Y; + float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceMouseDownPosition).Y - offsetFromReferenceOrigin; + + // Flip the vertical coordinate space when scrolling downwards + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + targetPosition = targetPosition - referenceParent.DrawHeight; + + float movementDelta = targetPosition - reference.HitObject.Position.Y; + + foreach (var b in SelectedBlueprints.OfType()) + b.HitObject.Y += movementDelta; + } + + private void performDragMovement(DragEvent dragEvent) + { + foreach (var b in SelectedBlueprints) { - var hitObject = blueprint.HitObject; + var hitObject = b.HitObject; var objectParent = (HitObjectContainer)hitObject.Parent; @@ -59,11 +92,9 @@ namespace osu.Game.Rulesets.Mania.Edit objectParent.Add(hitObject); } - - adjustColumn(dragEvent); } - private void adjustColumn(DragEvent dragEvent) + private void performColumnMovement(DragEvent dragEvent) { var lastColumn = composer.ColumnAt(dragEvent.ScreenSpaceLastMousePosition); var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceMousePosition); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 54f629cbea..0c7e571ef5 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -10,10 +11,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleDrag(DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { - base.HandleDrag(dragEvent); - foreach (var h in SelectedHitObjects.OfType()) { if (h is Spinner) @@ -24,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Edit h.Position += dragEvent.Delta; } + + base.HandleDrag(blueprint, dragEvent); } } } diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 04e8834946..ec4df01e55 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Edit /// /// Invoked when this has requested drag. /// - public event Action DragRequested; + public event Action DragRequested; /// /// The which this applies to. @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnDrag(DragEvent e) { - DragRequested?.Invoke(e); + DragRequested?.Invoke(this, e); return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 4664d521ec..80bfe21367 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -180,7 +180,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private void onDragRequested(DragEvent dragEvent) => selectionHandler.HandleDrag(dragEvent); + private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) => selectionHandler.HandleDrag(blueprint, dragEvent); private class SelectionBlueprintContainer : Container { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 0140f3aa75..f8ceeedba9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Input; @@ -66,8 +67,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Handles the selected s being dragged. /// + /// The that received the drag event. /// The drag event. - public virtual void HandleDrag(DragEvent dragEvent) + public virtual void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { } From c5d2dc2f6a4e0751d0592f0ea028232017c5e34e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 13:05:17 +0900 Subject: [PATCH 11/76] Remove unnecessary newline --- osu.Game/Database/IHasFiles.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index 3aaba37efc..6ccb1f5722 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.cs @@ -11,7 +11,6 @@ namespace osu.Game.Database /// The model representing a file. public interface IHasFiles where TFile : INamedFileInfo - { List Files { get; set; } } From ea52d2d527ff669a8acdc246e706d4ec36e6504a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 13:12:29 +0900 Subject: [PATCH 12/76] Make Mod IJsonSerializable --- osu.Game/Rulesets/Mods/Mod.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index a991f7e7b0..81ebca2fe3 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -3,17 +3,20 @@ using osu.Game.Graphics; using System; +using Newtonsoft.Json; +using osu.Game.IO.Serialization; namespace osu.Game.Rulesets.Mods { /// /// The base class for gameplay modifiers. /// - public abstract class Mod + public abstract class Mod : IJsonSerializable { /// /// The name of this mod. /// + [JsonIgnore] public abstract string Name { get; } /// @@ -24,36 +27,43 @@ namespace osu.Game.Rulesets.Mods /// /// The icon of this mod. /// + [JsonIgnore] public virtual FontAwesome Icon => FontAwesome.fa_question; /// /// The type of this mod. /// + [JsonIgnore] public virtual ModType Type => ModType.Fun; /// /// The user readable description of this mod. /// + [JsonIgnore] public virtual string Description => string.Empty; /// /// The score multiplier of this mod. /// + [JsonIgnore] public abstract double ScoreMultiplier { get; } /// /// Returns true if this mod is implemented (and playable). /// + [JsonIgnore] public virtual bool HasImplementation => this is IApplicableMod; /// /// Returns if this mod is ranked. /// + [JsonIgnore] public virtual bool Ranked => false; /// /// The mods this mod cannot be enabled with. /// + [JsonIgnore] public virtual Type[] IncompatibleMods => new Type[] { }; } } From 14ff4bc26a3456d8b0d6f6d5657306dd4cdb659d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 13:19:23 +0900 Subject: [PATCH 13/76] Move primary key attribute to IHasPrimaryKey --- osu.Game/Beatmaps/BeatmapDifficulty.cs | 5 ++--- osu.Game/Beatmaps/BeatmapInfo.cs | 1 - osu.Game/Beatmaps/BeatmapMetadata.cs | 4 ++-- osu.Game/Beatmaps/BeatmapSetFileInfo.cs | 4 +--- osu.Game/Beatmaps/BeatmapSetInfo.cs | 1 - osu.Game/Configuration/DatabasedSetting.cs | 1 - osu.Game/Database/IHasPrimaryKey.cs | 3 +++ osu.Game/IO/FileInfo.cs | 5 ++--- osu.Game/Input/Bindings/DatabasedKeyBinding.cs | 1 - osu.Game/Skinning/SkinFileInfo.cs | 4 +--- osu.Game/Skinning/SkinInfo.cs | 2 -- 11 files changed, 11 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 508232dbfe..a6d69f322d 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -1,19 +1,18 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; +using osu.Game.Database; namespace osu.Game.Beatmaps { - public class BeatmapDifficulty + public class BeatmapDifficulty : IHasPrimaryKey { /// /// The default value used for all difficulty settings except and . /// public const float DEFAULT_DIFFICULTY = 5; - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [JsonIgnore] public int ID { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3e1f3bdf54..7479e1bbdb 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -15,7 +15,6 @@ namespace osu.Game.Beatmaps [Serializable] public class BeatmapInfo : IEquatable, IJsonSerializable, IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [JsonIgnore] public int ID { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 57983ec568..7e4dc4d6f5 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -6,14 +6,14 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using Newtonsoft.Json; +using osu.Game.Database; using osu.Game.Users; namespace osu.Game.Beatmaps { [Serializable] - public class BeatmapMetadata : IEquatable + public class BeatmapMetadata : IEquatable, IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public string Title { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs index 4fa286cbec..885fcc54f6 100644 --- a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs @@ -2,15 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; using osu.Game.IO; namespace osu.Game.Beatmaps { - public class BeatmapSetFileInfo : INamedFileInfo + public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public int BeatmapSetInfoID { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 7a7d010a31..8c541e9344 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -10,7 +10,6 @@ namespace osu.Game.Beatmaps { public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles, ISoftDelete { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } private int? onlineBeatmapSetID; diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index 62990991b0..6c2822734b 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -9,7 +9,6 @@ namespace osu.Game.Configuration [Table("Settings")] public class DatabasedSetting : IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public int? RulesetID { get; set; } diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index 2ee356baea..71e8867fa7 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.cs @@ -1,10 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel.DataAnnotations.Schema; + namespace osu.Game.Database { public interface IHasPrimaryKey { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] int ID { get; set; } } } diff --git a/osu.Game/IO/FileInfo.cs b/osu.Game/IO/FileInfo.cs index 1804be90a0..edd389bc65 100644 --- a/osu.Game/IO/FileInfo.cs +++ b/osu.Game/IO/FileInfo.cs @@ -1,14 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.ComponentModel.DataAnnotations.Schema; using System.IO; +using osu.Game.Database; namespace osu.Game.IO { - public class FileInfo + public class FileInfo : IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public string Hash { get; set; } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index 7a230f32a0..e69dd30822 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -10,7 +10,6 @@ namespace osu.Game.Input.Bindings [Table("KeyBinding")] public class DatabasedKeyBinding : KeyBinding, IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public int? RulesetID { get; set; } diff --git a/osu.Game/Skinning/SkinFileInfo.cs b/osu.Game/Skinning/SkinFileInfo.cs index c9a3b0e94c..8f0f2b536a 100644 --- a/osu.Game/Skinning/SkinFileInfo.cs +++ b/osu.Game/Skinning/SkinFileInfo.cs @@ -2,15 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; using osu.Game.IO; namespace osu.Game.Skinning { - public class SkinFileInfo : INamedFileInfo + public class SkinFileInfo : INamedFileInfo, IHasPrimaryKey { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public int SkinInfoID { get; set; } diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 47dad60d88..423e7c0780 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -3,14 +3,12 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; namespace osu.Game.Skinning { public class SkinInfo : IHasFiles, IEquatable, IHasPrimaryKey, ISoftDelete { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } public string Name { get; set; } From dc31736db750e9c37f9b57f08e132ca5aba5a2c3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 13:42:36 +0900 Subject: [PATCH 14/76] Add explicit foreign key property to INamedFileInfo --- osu.Game/Database/INamedFileInfo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Database/INamedFileInfo.cs b/osu.Game/Database/INamedFileInfo.cs index 751024d184..04dcdad285 100644 --- a/osu.Game/Database/INamedFileInfo.cs +++ b/osu.Game/Database/INamedFileInfo.cs @@ -10,7 +10,11 @@ namespace osu.Game.Database /// public interface INamedFileInfo { + // An explicit foreign key property isn't required but is recommended and may be helpful to have + int FileInfoID { get; set; } + FileInfo FileInfo { get; set; } + string Filename { get; set; } } } From 0982508d26d04a6e81333fe67989adc74daf4f41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 15:13:27 +0900 Subject: [PATCH 15/76] Rename to LegacyDirectoryArchiveReader --- osu.Game/Database/ArchiveModelManager.cs | 2 +- ...yFilesystemReader.cs => LegacyDirectoryArchiveReader.cs} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/IO/Archives/{LegacyFilesystemReader.cs => LegacyDirectoryArchiveReader.cs} (85%) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3686b702c4..3388074ffc 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -485,7 +485,7 @@ namespace osu.Game.Database if (ZipUtils.IsZipArchive(path)) return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)); if (Directory.Exists(path)) - return new LegacyFilesystemReader(path); + return new LegacyDirectoryArchiveReader(path); throw new InvalidFormatException($"{path} is not a valid archive"); } } diff --git a/osu.Game/IO/Archives/LegacyFilesystemReader.cs b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs similarity index 85% rename from osu.Game/IO/Archives/LegacyFilesystemReader.cs rename to osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs index dcaaf41c77..cad056b66a 100644 --- a/osu.Game/IO/Archives/LegacyFilesystemReader.cs +++ b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs @@ -8,13 +8,13 @@ using System.Linq; namespace osu.Game.IO.Archives { /// - /// Reads an extracted legacy beatmap from disk. + /// Reads an archive from a directory on disk. /// - public class LegacyFilesystemReader : ArchiveReader + public class LegacyDirectoryArchiveReader : ArchiveReader { private readonly string path; - public LegacyFilesystemReader(string path) + public LegacyDirectoryArchiveReader(string path) : base(Path.GetFileName(path)) { // re-get full path to standardise with Directory.GetFiles return values below. From 5fd6e6ca7785f1003728926f528859927bb64cb2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 16:12:57 +0900 Subject: [PATCH 16/76] Re-namespacing --- osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs | 1 + .../Difficulty/ManiaPerformanceCalculator.cs | 1 + osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs | 1 + .../Difficulty/OsuPerformanceCalculator.cs | 1 + osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 1 + osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 1 + .../Difficulty/TaikoPerformanceCalculator.cs | 1 + osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs | 1 + osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs | 1 + osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 1 + osu.Game.Tests/Visual/TestCaseResults.cs | 1 + .../Online/API/Requests/Responses/APIRecentActivity.cs | 1 + osu.Game/Online/API/Requests/Responses/APIScore.cs | 1 + osu.Game/OsuGame.cs | 1 + osu.Game/OsuGameBase.cs | 1 + osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs | 1 + .../Profile/Sections/Ranks/DrawablePerformanceScore.cs | 1 + .../Profile/Sections/Ranks/DrawableProfileScore.cs | 1 + .../Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs | 1 + osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs | 1 + osu.Game/Rulesets/Mods/ModAutoplay.cs | 1 + osu.Game/Rulesets/Ruleset.cs | 1 + osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 1 + .../Scoring/Legacy/DatabasedLegacyScoreParser.cs | 3 ++- .../{Rulesets => }/Scoring/Legacy/LegacyScoreParser.cs | 8 +++++--- osu.Game/{Rulesets => }/Scoring/Score.cs | 2 +- osu.Game/{Rulesets => }/Scoring/ScoreRank.cs | 2 +- osu.Game/{Rulesets => }/Scoring/ScoreStore.cs | 2 +- osu.Game/Screens/Play/Break/BreakInfo.cs | 2 +- osu.Game/Screens/Play/Player.cs | 1 + osu.Game/Screens/Ranking/Results.cs | 2 +- osu.Game/Screens/Ranking/ResultsPage.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageRanking.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 1 + osu.Game/Screens/Select/Leaderboards/DrawableRank.cs | 2 +- osu.Game/Screens/Select/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs | 3 +-- 40 files changed, 45 insertions(+), 15 deletions(-) rename osu.Game/{Rulesets => }/Scoring/Legacy/DatabasedLegacyScoreParser.cs (94%) rename osu.Game/{Rulesets => }/Scoring/Legacy/LegacyScoreParser.cs (98%) rename osu.Game/{Rulesets => }/Scoring/Score.cs (96%) rename osu.Game/{Rulesets => }/Scoring/ScoreRank.cs (94%) rename osu.Game/{Rulesets => }/Scoring/ScoreStore.cs (98%) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 5ed563614a..ea60bc307d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Users; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 1f26bda1b2..61aa83b04e 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -8,6 +8,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania.Difficulty { diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 19e89c8ec5..194fde94c0 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -25,6 +25,7 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 89792956bb..14c6798ef8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Users; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index b0887ac72b..86dcb54913 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Difficulty { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index 1eb2f59010..bae7a0d3ab 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Mods { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6736d10dab..2437657971 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -20,6 +20,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Difficulty; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu { diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index a9d39e88b4..a924ac8779 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Scoring { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 734d5d0ad7..811bac2759 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Taiko.Difficulty { diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index c63bf10542..9e2fd4e6d8 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Scoring; using osu.Game.Users; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7d9bc98957..7de8d4dbbf 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Taiko { diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index d3098864f4..9edf0708e0 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Osu; +using osu.Game.Scoring; namespace osu.Game.Tests.Visual { diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index d4a2fcc62c..b506d18087 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -13,6 +13,7 @@ using osuTK; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Scoring; namespace osu.Game.Tests.Visual { diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index ee36fb0afc..62ab89db3c 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 2c65a37cf8..391b24b077 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -5,6 +5,7 @@ using System; using Humanizer; using Newtonsoft.Json; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Online.API.Requests.Responses { diff --git a/osu.Game/Online/API/Requests/Responses/APIScore.cs b/osu.Game/Online/API/Requests/Responses/APIScore.cs index 25eb32a79f..a5b2f391da 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScore.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Users; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d91f96db53..a17b638d6d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -37,6 +37,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Skinning; using osuTK.Graphics; using osu.Game.Overlays.Volume; +using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c267c323a6..efa1a346be 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -29,6 +29,7 @@ using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Skinning; using osuTK.Input; using DebugUtils = osu.Game.Utils.DebugUtils; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index aa785385ba..4adca78072 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -16,6 +16,7 @@ using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index ddbe10c05c..772d74193f 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index a20054351d..028533b062 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index 3a39ef5d61..b65ded78a8 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks { diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index ba783ee87b..06169dbc3a 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -8,6 +8,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Difficulty { diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 5c03cb9736..c56f97434e 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 82d9945ef7..1c01a4cb49 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; +using osu.Game.Scoring; namespace osu.Game.Rulesets { diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b0cea7009e..23162a1b37 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring { diff --git a/osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs similarity index 94% rename from osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs rename to osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs index bfb2b7c13b..5866c04192 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/DatabasedLegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs @@ -2,8 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; +using osu.Game.Rulesets; -namespace osu.Game.Rulesets.Scoring.Legacy +namespace osu.Game.Scoring.Legacy { /// /// A which retrieves the applicable and diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs similarity index 98% rename from osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs rename to osu.Game/Scoring/Legacy/LegacyScoreParser.cs index a90cd79186..9a683cf555 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -3,16 +3,18 @@ using System; using System.IO; +using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; using osu.Game.IO.Legacy; +using osu.Game.Rulesets; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Legacy; +using osu.Game.Rulesets.Scoring; using osu.Game.Users; using SharpCompress.Compressors.LZMA; -using osu.Game.Beatmaps.Legacy; -using System.Linq; -namespace osu.Game.Rulesets.Scoring.Legacy +namespace osu.Game.Scoring.Legacy { public abstract class LegacyScoreParser { diff --git a/osu.Game/Rulesets/Scoring/Score.cs b/osu.Game/Scoring/Score.cs similarity index 96% rename from osu.Game/Rulesets/Scoring/Score.cs rename to osu.Game/Scoring/Score.cs index 02f528791a..d0d284f77b 100644 --- a/osu.Game/Rulesets/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Users; using osu.Game.Rulesets.Replays; -namespace osu.Game.Rulesets.Scoring +namespace osu.Game.Scoring { public class Score { diff --git a/osu.Game/Rulesets/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs similarity index 94% rename from osu.Game/Rulesets/Scoring/ScoreRank.cs rename to osu.Game/Scoring/ScoreRank.cs index d4113bb08a..efc513c39c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -namespace osu.Game.Rulesets.Scoring +namespace osu.Game.Scoring { public enum ScoreRank { diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs similarity index 98% rename from osu.Game/Rulesets/Scoring/ScoreStore.cs rename to osu.Game/Scoring/ScoreStore.cs index 091cb29a71..bcdff8fdc3 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -10,7 +10,7 @@ using osu.Game.Database; using osu.Game.IPC; using osu.Game.Rulesets.Scoring.Legacy; -namespace osu.Game.Rulesets.Scoring +namespace osu.Game.Scoring { public class ScoreStore : DatabaseBackedStore, ICanAcceptFiles { diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index e5dbb6aa83..22e19ac8e2 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osuTK; namespace osu.Game.Screens.Play.Break diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a220a05971..7272987748 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -27,6 +27,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Skinning; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 57bb229517..cd952c9ca2 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -7,7 +7,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Scoring; using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Graphics.Containers; @@ -18,6 +17,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; +using osu.Game.Scoring; namespace osu.Game.Screens.Ranking { diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index f73bcba553..d6b711230c 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index 3509d536b2..e7d5d45930 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -5,10 +5,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select.Leaderboards; using osuTK; using osu.Framework.Graphics.Shapes; +using osu.Game.Scoring; namespace osu.Game.Screens.Ranking { diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 7f152aaf14..f4a4ff14bf 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -24,6 +24,7 @@ using osu.Game.Users; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions; using osu.Framework.Localisation; +using osu.Game.Scoring; namespace osu.Game.Screens.Ranking { diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 0cf1e60304..3258a62adf 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Extensions; -using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 0748f68dca..4023353caf 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -14,12 +14,12 @@ using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Scoring; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using System.Linq; using osu.Framework.Configuration; using osu.Game.Rulesets; +using osu.Game.Scoring; namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 19363fe0f9..d144250aed 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -14,8 +13,8 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Users; namespace osu.Game.Screens.Select.Leaderboards From a783fdb5010889f57d77dd67f50e04d9ff4ae1a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 16:13:16 +0900 Subject: [PATCH 17/76] Add LegacyFileArchiveReader Treats files as "archives" for import. --- osu.Game/Database/ArchiveModelManager.cs | 2 ++ .../IO/Archives/LegacyFileArchiveReader.cs | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 osu.Game/IO/Archives/LegacyFileArchiveReader.cs diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3388074ffc..364a3945d2 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -486,6 +486,8 @@ namespace osu.Game.Database return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)); if (Directory.Exists(path)) return new LegacyDirectoryArchiveReader(path); + if (File.Exists(path)) + return new LegacyFileArchiveReader(path); throw new InvalidFormatException($"{path} is not a valid archive"); } } diff --git a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs new file mode 100644 index 0000000000..28b5e628e4 --- /dev/null +++ b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.IO; + +namespace osu.Game.IO.Archives +{ + /// + /// Reads a file on disk as an archive. + /// Note: In this case, the file is not an extractable archive, use instead. + /// + public class LegacyFileArchiveReader : ArchiveReader + { + private readonly string path; + + public LegacyFileArchiveReader(string path) + : base(Path.GetFileName(path)) + { + // re-get full path to standardise + this.path = Path.GetFullPath(path); + } + + public override Stream GetStream(string name) => File.OpenRead(path); + + public override void Dispose() + { + } + + public override IEnumerable Filenames => new[] { Name }; + + public override Stream GetUnderlyingStream() => null; + } +} From 09b79d736b1eaf0ae94db76f6b1851397ad1c24e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 16:33:42 +0900 Subject: [PATCH 18/76] Remove unused usings --- osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs | 1 - osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 - osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 1 - osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 - osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs | 1 - osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 - osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 1 - osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs | 1 - osu.Game/OsuGame.cs | 1 - osu.Game/OsuGameBase.cs | 1 - .../Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs | 1 - .../Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs | 1 - osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs | 1 - osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs | 1 - osu.Game/Rulesets/Mods/ModAutoplay.cs | 1 - osu.Game/Rulesets/Ruleset.cs | 1 - osu.Game/Scoring/Score.cs | 2 ++ osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs | 1 + 19 files changed, 3 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index ea60bc307d..5bfa11e6de 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -5,7 +5,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 194fde94c0..9e7ce8b0a4 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -24,7 +24,6 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Edit; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 14c6798ef8..085c75b7d5 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index bae7a0d3ab..b074b02ef9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -7,7 +7,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Mods diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 2437657971..b0bd5be503 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -11,7 +11,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Replays; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index 9e2fd4e6d8..eedc70d814 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -3,7 +3,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Scoring; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7de8d4dbbf..57a69e0b84 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Difficulty; using osu.Game.Scoring; diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index b506d18087..d03a7dd889 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; using osu.Framework.Graphics; -using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osu.Framework.Allocation; diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 391b24b077..c38c443ec3 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -4,7 +4,6 @@ using System; using Humanizer; using Newtonsoft.Json; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a17b638d6d..5ed66f5614 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -27,7 +27,6 @@ using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Input; -using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Screens.Play; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index efa1a346be..ecec6e0280 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -28,7 +28,6 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Rulesets; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; using osuTK.Input; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index 772d74193f..a6e81f0e3b 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 028533b062..6964d43a08 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -8,7 +8,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select.Leaderboards; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index b65ded78a8..039b00e3b1 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 06169dbc3a..d1ebb39f0f 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -7,7 +7,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Rulesets.Difficulty diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index c56f97434e..de4581c9c2 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -6,7 +6,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 1c01a4cb49..a161a0a5e4 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -12,7 +12,6 @@ using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index d0d284f77b..f81de97d01 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Beatmaps; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring { diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index d144250aed..32bc7e42b6 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; From 3fe4a36845a3f182c73148bec914a668b2339d5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 16:39:08 +0900 Subject: [PATCH 19/76] Add databased fields to Score --- osu.Game/Scoring/Score.cs | 43 ++++++++++++++++++++++++++++++- osu.Game/Scoring/ScoreFileInfo.cs | 21 +++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Scoring/ScoreFileInfo.cs diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index f81de97d01..36f37f5d7a 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -3,8 +3,12 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; @@ -13,8 +17,11 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring { - public class Score + public class Score : IHasFiles, IHasPrimaryKey, ISoftDelete { + [JsonIgnore] + public int ID { get; set; } + public ScoreRank Rank { get; set; } public double TotalScore { get; set; } @@ -31,10 +38,30 @@ namespace osu.Game.Scoring public RulesetInfo Ruleset { get; set; } + [NotMapped] + [JsonIgnore] public Mod[] Mods { get; set; } = { }; + public string ModsString + { + get => JsonConvert.SerializeObject(Mods); + set + { + var deserialized = JsonConvert.DeserializeObject(value); + Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d.ShortenedName == mod.ShortenedName)).ToArray(); + } + } + + [NotMapped] + [JsonIgnore] public User User; + public string UserString + { + get => User?.Username; + set => User = new User { Username = value }; + } + [JsonIgnore] public Replay Replay; @@ -45,5 +72,19 @@ namespace osu.Game.Scoring public DateTimeOffset Date; public Dictionary Statistics = new Dictionary(); + + public List Files { get; set; } + + public bool DeletePending { get; set; } + + [UsedImplicitly] + private class SerializableMod : Mod + { + public override string Name => ShortenedName; + + public override string ShortenedName { get; } = string.Empty; + + public override double ScoreMultiplier => 0; + } } } diff --git a/osu.Game/Scoring/ScoreFileInfo.cs b/osu.Game/Scoring/ScoreFileInfo.cs new file mode 100644 index 0000000000..e5595397b8 --- /dev/null +++ b/osu.Game/Scoring/ScoreFileInfo.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel.DataAnnotations; +using osu.Game.Database; +using osu.Game.IO; + +namespace osu.Game.Scoring +{ + public class ScoreFileInfo : INamedFileInfo, IHasPrimaryKey + { + public int ID { get; set; } + + public int FileInfoID { get; set; } + + public FileInfo FileInfo { get; set; } + + [Required] + public string Filename { get; set; } + } +} From 4ba7690e0440d98b355c07fef2ec99f442e9372f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 16:47:10 +0900 Subject: [PATCH 20/76] Initial scoremanager/scorestore structure --- osu.Game/Database/OsuDbContext.cs | 2 ++ osu.Game/IPC/ScoreIPCChannel.cs | 46 --------------------------- osu.Game/OsuGame.cs | 2 +- osu.Game/OsuGameBase.cs | 8 ++--- osu.Game/Scoring/ScoreManager.cs | 31 ++++++++++++++++++ osu.Game/Scoring/ScoreStore.cs | 53 ++++--------------------------- 6 files changed, 45 insertions(+), 97 deletions(-) delete mode 100644 osu.Game/IPC/ScoreIPCChannel.cs create mode 100644 osu.Game/Scoring/ScoreManager.cs diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 20e144c033..b823ea8b28 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -10,6 +10,7 @@ using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.IO; using osu.Game.Rulesets; +using osu.Game.Scoring; using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding; using LogLevel = Microsoft.Extensions.Logging.LogLevel; using osu.Game.Skinning; @@ -27,6 +28,7 @@ namespace osu.Game.Database public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } public DbSet SkinInfo { get; set; } + public DbSet ScoreInfo { get; set; } private readonly string connectionString; diff --git a/osu.Game/IPC/ScoreIPCChannel.cs b/osu.Game/IPC/ScoreIPCChannel.cs deleted file mode 100644 index a66b8ce1f3..0000000000 --- a/osu.Game/IPC/ScoreIPCChannel.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Diagnostics; -using System.Threading.Tasks; -using osu.Framework.Platform; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.IPC -{ - public class ScoreIPCChannel : IpcChannel - { - private readonly ScoreStore scores; - - public ScoreIPCChannel(IIpcHost host, ScoreStore scores = null) - : base(host) - { - this.scores = scores; - MessageReceived += msg => - { - Debug.Assert(scores != null); - ImportAsync(msg.Path).ContinueWith(t => - { - if (t.Exception != null) throw t.Exception; - }, TaskContinuationOptions.OnlyOnFaulted); - }; - } - - public async Task ImportAsync(string path) - { - if (scores == null) - { - //we want to contact a remote osu! to handle the import. - await SendMessageAsync(new ScoreImportMessage { Path = path }); - return; - } - - scores.ReadReplayFile(path); - } - } - - public class ScoreImportMessage - { - public string Path; - } -} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5ed66f5614..4922030a07 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -148,7 +148,7 @@ namespace osu.Game { this.frameworkConfig = frameworkConfig; - ScoreStore.ScoreImported += score => Schedule(() => LoadScore(score)); + ScoreManager.ItemAdded += score => Schedule(() => LoadScore(score)); if (!Host.IsPrimaryInstance) { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ecec6e0280..2729676504 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -46,14 +46,14 @@ namespace osu.Game protected BeatmapManager BeatmapManager; + protected ScoreManager ScoreManager; + protected SkinManager SkinManager; protected RulesetStore RulesetStore; protected FileStore FileStore; - protected ScoreStore ScoreStore; - protected KeyBindingStore KeyBindingStore; protected SettingsStore SettingsStore; @@ -154,14 +154,14 @@ namespace osu.Game dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); - dependencies.Cache(ScoreStore = new ScoreStore(contextFactory, Host, BeatmapManager, RulesetStore)); + dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); dependencies.Cache(new OsuColour()); fileImporters.Add(BeatmapManager); - fileImporters.Add(ScoreStore); + fileImporters.Add(ScoreManager); fileImporters.Add(SkinManager); var defaultBeatmap = new DummyWorkingBeatmap(this); diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs new file mode 100644 index 0000000000..8e841a11b2 --- /dev/null +++ b/osu.Game/Scoring/ScoreManager.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.IO.Archives; +using osu.Game.Rulesets; + +namespace osu.Game.Scoring +{ + public class ScoreManager : ArchiveModelManager + { + public override string[] HandledExtensions => new[] { ".osr" }; + + protected override string ImportFromStablePath => "Replays"; + + public ScoreManager(RulesetStore rulesets, BeatmapManager beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) + : base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) + { + } + + protected override Score CreateModel(ArchiveReader archive) => new Score(); + + protected override void Populate(Score model, ArchiveReader archive) + { + if (archive == null) + return; + } + } +} diff --git a/osu.Game/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs index bcdff8fdc3..781b5c3755 100644 --- a/osu.Game/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -1,60 +1,21 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.IO; -using osu.Framework.Logging; +using System.Linq; +using Microsoft.EntityFrameworkCore; using osu.Framework.Platform; -using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.IPC; -using osu.Game.Rulesets.Scoring.Legacy; namespace osu.Game.Scoring { - public class ScoreStore : DatabaseBackedStore, ICanAcceptFiles + public class ScoreStore : MutableDatabaseBackedStore { - private readonly BeatmapManager beatmaps; - private readonly RulesetStore rulesets; - - private const string replay_folder = @"replays"; - - public event Action ScoreImported; - - // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) - private ScoreIPCChannel ipc; - - public ScoreStore(DatabaseContextFactory factory, IIpcHost importHost = null, BeatmapManager beatmaps = null, RulesetStore rulesets = null) : base(factory) + public ScoreStore(IDatabaseContextFactory factory, Storage storage) + : base(factory, storage) { - this.beatmaps = beatmaps; - this.rulesets = rulesets; - - if (importHost != null) - ipc = new ScoreIPCChannel(importHost, this); } - public string[] HandledExtensions => new[] { ".osr" }; - - public void Import(params string[] paths) - { - foreach (var path in paths) - { - var score = ReadReplayFile(path); - if (score != null) - ScoreImported?.Invoke(score); - } - } - - public Score ReadReplayFile(string replayFilename) - { - if (File.Exists(replayFilename)) - { - using (var stream = File.OpenRead(replayFilename)) - return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream); - } - - Logger.Log($"Replay file {replayFilename} cannot be found", LoggingTarget.Information, LogLevel.Error); - return null; - } + protected override IQueryable AddIncludesForConsumption(IQueryable query) + => base.AddIncludesForConsumption(query).Include(s => s.Files).ThenInclude(f => f.FileInfo); } } From 7a82b99417217051f3329c53590e4f930ddf24ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:02:14 +0900 Subject: [PATCH 21/76] Add storage for a few more parsed fields --- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 20 ++++++++------------ osu.Game/Scoring/Score.cs | 6 ++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 9a683cf555..60c7b03cf2 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -30,17 +30,13 @@ namespace osu.Game.Scoring.Legacy currentRuleset = GetRuleset(sr.ReadByte()); score = new Score { Ruleset = currentRuleset.RulesetInfo }; - /* score.Pass = true;*/ var version = sr.ReadInt32(); - /* score.FileChecksum = */ currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; score.Beatmap = currentBeatmap.BeatmapInfo; - /* score.PlayerName = */ score.User = new User { Username = sr.ReadString() }; - /* var localScoreChecksum = */ - sr.ReadString(); + score.MD5Hash = sr.ReadString(); var count300 = sr.ReadUInt16(); var count100 = sr.ReadUInt16(); @@ -58,23 +54,23 @@ namespace osu.Game.Scoring.Legacy score.TotalScore = sr.ReadInt32(); score.MaxCombo = sr.ReadUInt16(); + /* score.Perfect = */ sr.ReadBoolean(); - /* score.EnabledMods = (Mods)*/ + score.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); + /* score.HpGraphString = */ sr.ReadString(); - /* score.Date = */ - sr.ReadDateTime(); + + score.Date = sr.ReadDateTime(); var compressedReplay = sr.ReadByteArray(); if (version >= 20140721) - /*OnlineId =*/ - sr.ReadInt64(); + score.OnlineScoreID = sr.ReadInt64(); else if (version >= 20121008) - /*OnlineId =*/ - sr.ReadInt32(); + score.OnlineScoreID = sr.ReadInt32(); switch (score.Ruleset.ID) { diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 36f37f5d7a..5d3e05f006 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -73,6 +73,12 @@ namespace osu.Game.Scoring public Dictionary Statistics = new Dictionary(); + /// + /// MD5 is kept for legacy support. + /// + [JsonProperty("file_md5")] + public string MD5Hash { get; set; } + public List Files { get; set; } public bool DeletePending { get; set; } From 1717d7defb7e74f0eeac421bebecc3115b1c44da Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:19:58 +0900 Subject: [PATCH 22/76] Implement importing of scores into ScoreManager --- osu.Game/Scoring/ScoreManager.cs | 40 ++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8e841a11b2..08c8047078 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -1,11 +1,17 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.IO.Archives; using osu.Game.Rulesets; +using osu.Game.Scoring.Legacy; namespace osu.Game.Scoring { @@ -15,17 +21,43 @@ namespace osu.Game.Scoring protected override string ImportFromStablePath => "Replays"; + private readonly RulesetStore rulesets; + private readonly BeatmapManager beatmaps; + + private readonly ScoreStore scores; + public ScoreManager(RulesetStore rulesets, BeatmapManager beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) : base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) { + this.rulesets = rulesets; + this.beatmaps = beatmaps; + + scores = (ScoreStore)ModelStore; } - protected override Score CreateModel(ArchiveReader archive) => new Score(); - - protected override void Populate(Score model, ArchiveReader archive) + protected override Score CreateModel(ArchiveReader archive) { if (archive == null) - return; + return null; + + using (var stream = archive.GetStream(archive.Filenames.First(f => f.EndsWith(".osr")))) + return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream); } + + protected override Score CheckForExisting(Score model) + { + var existingHashMatch = scores.ConsumableItems.FirstOrDefault(s => s.MD5Hash == model.MD5Hash); + if (existingHashMatch != null) + { + Undelete(existingHashMatch); + return existingHashMatch; + } + + return null; + } + + public List GetAllScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + + public Score Query(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); } } From 2ee181daf7cdf0a3c01021d69382b9a3dbedf47e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:20:37 +0900 Subject: [PATCH 23/76] Re-namespace replay-related classes --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 1 + .../Replays/CatchFramedReplayInputHandler.cs | 1 + osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs | 2 +- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 1 + .../Replays/ManiaFramedReplayInputHandler.cs | 1 + osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs | 1 + osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs | 1 + osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs | 2 +- osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs | 1 + .../Replays/TaikoFramedReplayInputHandler.cs | 1 + osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIScore.cs | 2 +- osu.Game/{Rulesets => }/Replays/Legacy/LegacyReplayFrame.cs | 3 ++- osu.Game/{Rulesets => }/Replays/Legacy/ReplayButtonState.cs | 2 +- osu.Game/{Rulesets => }/Replays/Replay.cs | 3 ++- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Rulesets/Replays/AutoGenerator.cs | 1 + osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 1 + osu.Game/Rulesets/Replays/IAutoGenerator.cs | 2 ++ osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs | 2 +- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 3 ++- osu.Game/Scoring/Score.cs | 2 +- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- 30 files changed, 34 insertions(+), 19 deletions(-) rename osu.Game/{Rulesets => }/Replays/Legacy/LegacyReplayFrame.cs (95%) rename osu.Game/{Rulesets => }/Replays/Legacy/ReplayButtonState.cs (88%) rename osu.Game/{Rulesets => }/Replays/Replay.cs (85%) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 23b620248f..b0376b547d 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using osu.Framework.MathUtils; using osu.Game.Beatmaps; +using osu.Game.Replays; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index f05eb31454..c907fec653 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; +using osu.Game.Replays; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Catch.Replays diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index d5c5eb844a..8c32b75959 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -2,9 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; +using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Legacy; using osu.Game.Rulesets.Replays.Types; namespace osu.Game.Rulesets.Catch.Replays diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index ef1bb7767f..3673657cd8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -5,12 +5,12 @@ using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Input.Handlers; +using osu.Game.Replays; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 0eef540d97..52672e6f17 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index ea239bf80f..20b0775c57 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Input.StateChanges; +using osu.Game.Replays; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index bc9fd6e06f..04d3bdf5f5 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Legacy; using osu.Game.Rulesets.Replays.Types; namespace osu.Game.Rulesets.Mania.Replays diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 321dd4e1cb..da322978c9 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; +using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Mods; @@ -21,7 +22,6 @@ using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index a0d040c40b..eda5be1f0f 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -8,8 +8,8 @@ using osu.Game.Rulesets.Osu.Objects; using System; using System.Linq; using osu.Framework.Graphics; +using osu.Game.Replays; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Replays diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 2530644413..12d130ef53 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -6,6 +6,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; using System; using System.Collections.Generic; +using osu.Game.Replays; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Replays; using osu.Game.Users; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 82dfa7f0ad..74250fb92d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Legacy; using osu.Game.Rulesets.Replays.Types; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs index 230709a4aa..7806e88b5c 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; +using osu.Game.Replays; using osu.Game.Rulesets.Replays; using osuTK; diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index ea5718bed2..c0e6eae494 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; +using osu.Game.Replays; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -14,7 +15,6 @@ using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Osu.UI { diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index e7b2789010..f089877f38 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Replays; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index ab7856eb8f..9748cb08be 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -5,6 +5,7 @@ using osu.Game.Rulesets.Replays; using System.Collections.Generic; using System.Linq; using osu.Framework.Input.StateChanges; +using osu.Game.Replays; namespace osu.Game.Rulesets.Taiko.Replays { diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 2177a3cbdc..44fd43d660 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using osu.Game.Beatmaps; +using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Legacy; using osu.Game.Rulesets.Replays.Types; namespace osu.Game.Rulesets.Taiko.Replays diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 99c83c243b..8f6e55c0d1 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; @@ -16,6 +15,7 @@ using System.Linq; using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; +using osu.Game.Replays; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI diff --git a/osu.Game/Online/API/Requests/Responses/APIScore.cs b/osu.Game/Online/API/Requests/Responses/APIScore.cs index a5b2f391da..b35bf99667 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScore.cs @@ -6,8 +6,8 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using osu.Game.Beatmaps; +using osu.Game.Replays; using osu.Game.Rulesets; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; diff --git a/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs similarity index 95% rename from osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs rename to osu.Game/Replays/Legacy/LegacyReplayFrame.cs index f6de11454c..ac9fd96ae6 100644 --- a/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs +++ b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs @@ -1,9 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Replays; using osuTK; -namespace osu.Game.Rulesets.Replays.Legacy +namespace osu.Game.Replays.Legacy { public class LegacyReplayFrame : ReplayFrame { diff --git a/osu.Game/Rulesets/Replays/Legacy/ReplayButtonState.cs b/osu.Game/Replays/Legacy/ReplayButtonState.cs similarity index 88% rename from osu.Game/Rulesets/Replays/Legacy/ReplayButtonState.cs rename to osu.Game/Replays/Legacy/ReplayButtonState.cs index ee09414287..ffeff55e96 100644 --- a/osu.Game/Rulesets/Replays/Legacy/ReplayButtonState.cs +++ b/osu.Game/Replays/Legacy/ReplayButtonState.cs @@ -3,7 +3,7 @@ using System; -namespace osu.Game.Rulesets.Replays.Legacy +namespace osu.Game.Replays.Legacy { [Flags] public enum ReplayButtonState diff --git a/osu.Game/Rulesets/Replays/Replay.cs b/osu.Game/Replays/Replay.cs similarity index 85% rename from osu.Game/Rulesets/Replays/Replay.cs rename to osu.Game/Replays/Replay.cs index 8fbe4c8194..966849c783 100644 --- a/osu.Game/Rulesets/Replays/Replay.cs +++ b/osu.Game/Replays/Replay.cs @@ -2,9 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Rulesets.Replays; using osu.Game.Users; -namespace osu.Game.Rulesets.Replays +namespace osu.Game.Replays { public class Replay { diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index de4581c9c2..3f3cab5854 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -4,8 +4,8 @@ using System; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Replays; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using osu.Game.Scoring; diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 3ac0c3297c..1b6f17a5e4 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -3,6 +3,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Beatmaps; +using osu.Game.Replays; namespace osu.Game.Rulesets.Replays { diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index b10c6e1f15..abe1a1520d 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; +using osu.Game.Replays; using osuTK; using osuTK.Input; diff --git a/osu.Game/Rulesets/Replays/IAutoGenerator.cs b/osu.Game/Rulesets/Replays/IAutoGenerator.cs index 4ef5f16f39..90aea199c8 100644 --- a/osu.Game/Rulesets/Replays/IAutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/IAutoGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Replays; + namespace osu.Game.Rulesets.Replays { public interface IAutoGenerator diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index fdd528f296..9ece4b80d5 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Rulesets.Replays.Legacy; +using osu.Game.Replays.Legacy; namespace osu.Game.Rulesets.Replays.Types { diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 0abd358113..5967cad8d1 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -19,8 +19,8 @@ using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Overlays; +using osu.Game.Replays; using osu.Game.Rulesets.Configuration; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.UI diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 60c7b03cf2..21640acd5d 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -7,9 +7,10 @@ using System.Linq; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.IO.Legacy; +using osu.Game.Replays; +using osu.Game.Replays.Legacy; using osu.Game.Rulesets; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Legacy; using osu.Game.Rulesets.Scoring; using osu.Game.Users; using SharpCompress.Compressors.LZMA; diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 5d3e05f006..4a7faf1a60 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -9,10 +9,10 @@ using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Replays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; -using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 6e2a2e4c9c..9204a49ac9 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Replays; +using osu.Game.Replays; namespace osu.Game.Screens.Play { From ed028477524de89cd1c461c7767ba49da3307d93 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:26:39 +0900 Subject: [PATCH 24/76] Beatmap -> BeatmapInfo + add foreign key --- osu.Game/Online/API/Requests/Responses/APIScore.cs | 8 ++++---- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 2 +- osu.Game/Scoring/Score.cs | 4 +++- osu.Game/Screens/Play/Player.cs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIScore.cs b/osu.Game/Online/API/Requests/Responses/APIScore.cs index b35bf99667..938cdbf98a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScore.cs @@ -58,7 +58,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"beatmap")] private BeatmapInfo beatmap { - set => Beatmap = value; + set => BeatmapInfo = value; } [JsonProperty(@"beatmapset")] @@ -67,10 +67,10 @@ namespace osu.Game.Online.API.Requests.Responses set { // extract the set ID to its correct place. - Beatmap.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID }; + BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID }; value.ID = 0; - Beatmap.Metadata = value; + BeatmapInfo.Metadata = value; } } @@ -110,7 +110,7 @@ namespace osu.Game.Online.API.Requests.Responses public void ApplyBeatmap(BeatmapInfo beatmap) { - Beatmap = beatmap; + BeatmapInfo = beatmap; ApplyRuleset(beatmap.Ruleset); } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 21640acd5d..ab795bb900 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -34,7 +34,7 @@ namespace osu.Game.Scoring.Legacy var version = sr.ReadInt32(); currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; - score.Beatmap = currentBeatmap.BeatmapInfo; + score.BeatmapInfo = currentBeatmap.BeatmapInfo; score.User = new User { Username = sr.ReadString() }; score.MD5Hash = sr.ReadString(); diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 4a7faf1a60..d042e621f2 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -65,7 +65,9 @@ namespace osu.Game.Scoring [JsonIgnore] public Replay Replay; - public BeatmapInfo Beatmap; + public int BeatmapInfoID { get; set; } + + public BeatmapInfo BeatmapInfo; public long OnlineScoreID; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7272987748..49b71b4766 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -275,7 +275,7 @@ namespace osu.Game.Screens.Play var score = new Score { - Beatmap = Beatmap.Value.BeatmapInfo, + BeatmapInfo = Beatmap.Value.BeatmapInfo, Ruleset = ruleset }; ScoreProcessor.PopulateScore(score); From 41a8a12df35b7b18db9b0cc700c500c36e0115db Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:26:46 +0900 Subject: [PATCH 25/76] Add ruleset foreign key --- osu.Game/Scoring/Score.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index d042e621f2..0e894200b5 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -36,6 +36,8 @@ namespace osu.Game.Scoring public int Combo { get; set; } + public int RulesetID { get; set; } + public RulesetInfo Ruleset { get; set; } [NotMapped] From 5b409a5ae5ecded7ac6715ac6a0c3120db37cb7e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 17:27:22 +0900 Subject: [PATCH 26/76] Fix missed renames --- osu.Game/OsuGame.cs | 4 ++-- .../Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageRanking.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4922030a07..c6112aadb8 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -267,7 +267,7 @@ namespace osu.Game return; } - if (score.Beatmap == null) + if (score.BeatmapInfo == null) { notifications.Post(new SimpleNotification { @@ -279,7 +279,7 @@ namespace osu.Game ruleset.Value = score.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.Beatmap); + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.BeatmapInfo); Beatmap.Value.Mods.Value = score.Mods; menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 6964d43a08..b3251bba1d 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RightFlowContainer.Add(text); RightFlowContainer.SetLayoutPosition(text, 1); - LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap)); + LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.BeatmapInfo)); LeftFlowContainer.Add(new DrawableDate(Score.Date)); foreach (Mod mod in Score.Mods) diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index e7d5d45930..397b1a5905 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.Centre, Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Beatmap = Beatmap.BeatmapInfo ?? Score.Beatmap, + Beatmap = Beatmap.BeatmapInfo ?? Score.BeatmapInfo, Scale = new Vector2(0.7f) } }; From 219929eb4798252c4bdac23dd6d6e45d263511a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 18:33:01 +0900 Subject: [PATCH 27/76] Score -> ScoreInfo --- .../Mods/CatchModAutoplay.cs | 4 +- .../Difficulty/ManiaPerformanceCalculator.cs | 20 +++---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Mods/ManiaModAutoplay.cs | 4 +- .../Difficulty/OsuPerformanceCalculator.cs | 18 +++---- osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 4 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 12 ++--- .../Difficulty/TaikoPerformanceCalculator.cs | 20 +++---- .../Mods/TaikoModAutoplay.cs | 4 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../Visual/TestCaseBeatmapScoresContainer.cs | 36 ++++++------- osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 20 +++---- osu.Game.Tests/Visual/TestCaseResults.cs | 4 +- osu.Game/Database/OsuDbContext.cs | 2 +- .../Online/API/Requests/GetScoresRequest.cs | 2 +- .../API/Requests/GetUserScoresRequest.cs | 2 +- .../{APIScore.cs => APIScoreInfo.cs} | 2 +- .../API/Requests/Responses/APIScores.cs | 2 +- osu.Game/OsuGame.cs | 16 +++--- .../BeatmapSet/Scores/DrawableScore.cs | 16 +++--- .../BeatmapSet/Scores/DrawableTopScore.cs | 26 +++++----- .../BeatmapSet/Scores/ScoresContainer.cs | 6 +-- .../Ranks/DrawablePerformanceScore.cs | 6 +-- .../Sections/Ranks/DrawableProfileScore.cs | 16 +++--- .../Sections/Ranks/DrawableTotalScore.cs | 6 +-- .../Sections/Ranks/PaginatedScoreContainer.cs | 2 +- .../Difficulty/PerformanceCalculator.cs | 12 ++--- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 16 +++--- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 52 +++++++++---------- osu.Game/Scoring/{Score.cs => ScoreInfo.cs} | 2 +- osu.Game/Scoring/ScoreManager.cs | 10 ++-- osu.Game/Scoring/ScoreStore.cs | 4 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Ranking/Results.cs | 14 ++--- osu.Game/Screens/Ranking/ResultsPage.cs | 6 +-- .../Screens/Ranking/ResultsPageRanking.cs | 4 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 12 ++--- .../Select/Leaderboards/Leaderboard.cs | 6 +-- .../Select/Leaderboards/LeaderboardScore.cs | 22 ++++---- 42 files changed, 211 insertions(+), 211 deletions(-) rename osu.Game/Online/API/Requests/Responses/{APIScore.cs => APIScoreInfo.cs} (98%) rename osu.Game/Scoring/{Score.cs => ScoreInfo.cs} (96%) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 5bfa11e6de..2b8324d327 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) + protected override ScoreInfo CreateReplayScore(Beatmap beatmap) { - return new Score + return new ScoreInfo { User = new User { Username = "osu!salad!" }, Replay = new CatchAutoGenerator(beatmap).Generate(), diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 61aa83b04e..a845f1d2ad 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -28,21 +28,21 @@ namespace osu.Game.Rulesets.Mania.Difficulty private int countMeh; private int countMiss; - public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) - : base(ruleset, beatmap, score) + public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) + : base(ruleset, beatmap, scoreInfo) { } public override double Calculate(Dictionary categoryDifficulty = null) { - mods = Score.Mods; - scaledScore = Score.TotalScore; - countPerfect = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countOk = Convert.ToInt32(Score.Statistics[HitResult.Ok]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + mods = ScoreInfo.Mods; + scaledScore = ScoreInfo.TotalScore; + countPerfect = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Perfect]); + countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); + countOk = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Ok]); + countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); if (mods.Any(m => !m.Ranked)) return 0; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 9e7ce8b0a4..e02e6225e3 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new ManiaPerformanceCalculator(this, beatmap, scoreInfo); public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 085c75b7d5..1629a3916d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -13,9 +13,9 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) + protected override ScoreInfo CreateReplayScore(Beatmap beatmap) { - return new Score + return new ScoreInfo { User = new User { Username = "osu!topus!" }, Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 86dcb54913..ed6bdbd155 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty private int countMeh; private int countMiss; - public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) - : base(ruleset, beatmap, score) + public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) + : base(ruleset, beatmap, scoreInfo) { countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); @@ -42,13 +42,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty public override double Calculate(Dictionary categoryRatings = null) { - mods = Score.Mods; - accuracy = Score.Accuracy; - scoreMaxCombo = Score.MaxCombo; - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + mods = ScoreInfo.Mods; + accuracy = ScoreInfo.Accuracy; + scoreMaxCombo = ScoreInfo.MaxCombo; + countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index b074b02ef9..c998f36792 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -15,9 +15,9 @@ namespace osu.Game.Rulesets.Osu.Mods { public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray(); - protected override Score CreateReplayScore(Beatmap beatmap) + protected override ScoreInfo CreateReplayScore(Beatmap beatmap) { - return new Score + return new ScoreInfo { Replay = new OsuAutoGenerator(beatmap).Generate() }; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index b0bd5be503..dac9181fc9 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new OsuPerformanceCalculator(this, beatmap, scoreInfo); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index a924ac8779..cec6c50677 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -40,14 +40,14 @@ namespace osu.Game.Rulesets.Osu.Scoring comboResultCounts.Clear(); } - public override void PopulateScore(Score score) + public override void PopulateScore(ScoreInfo scoreInfo) { - base.PopulateScore(score); + base.PopulateScore(scoreInfo); - score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); - score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); - score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); - score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); + scoreInfo.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); + scoreInfo.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); + scoreInfo.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); + scoreInfo.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); } private const double harshness = 0.01; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 811bac2759..788c09d75a 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -23,18 +23,18 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private int countMeh; private int countMiss; - public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) - : base(ruleset, beatmap, score) + public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) + : base(ruleset, beatmap, scoreInfo) { } public override double Calculate(Dictionary categoryDifficulty = null) { - mods = Score.Mods; - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + mods = ScoreInfo.Mods; + countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty // Combo scaling if (Attributes.MaxCombo > 0) - strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); + strainValue *= Math.Min(Math.Pow(ScoreInfo.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); if (mods.Any(m => m is ModHidden)) strainValue *= 1.025; @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty strainValue *= 1.05 * lengthBonus; // Scale the speed value with accuracy _slightly_ - return strainValue * Score.Accuracy; + return strainValue * ScoreInfo.Accuracy; } private double computeAccuracyValue() @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; + double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(ScoreInfo.Accuracy, 15) * 22.0; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index eedc70d814..ff64ecf1bd 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) + protected override ScoreInfo CreateReplayScore(Beatmap beatmap) { - return new Score + return new ScoreInfo { User = new User { Username = "mekkadosu!" }, Replay = new TaikoAutoGenerator(beatmap).Generate(), diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 57a69e0b84..9b425c0ce9 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new TaikoPerformanceCalculator(this, beatmap, scoreInfo); public override int? LegacyID => 1; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index 9edf0708e0..ec85b33919 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -23,9 +23,9 @@ namespace osu.Game.Tests.Visual [System.ComponentModel.Description("in BeatmapOverlay")] public class TestCaseBeatmapScoresContainer : OsuTestCase { - private readonly IEnumerable scores; - private readonly IEnumerable anotherScores; - private readonly APIScore topScore; + private readonly IEnumerable scores; + private readonly IEnumerable anotherScores; + private readonly APIScoreInfo topScoreInfo; private readonly Box background; public TestCaseBeatmapScoresContainer() @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual AddStep("scores pack 1", () => scoresContainer.Scores = scores); AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); - AddStep("only top score", () => scoresContainer.Scores = new[] { topScore }); + AddStep("only top score", () => scoresContainer.Scores = new[] { topScoreInfo }); AddStep("remove scores", () => scoresContainer.Scores = null); AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual scores = new[] { - new APIScore + new APIScoreInfo { User = new User { @@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual TotalScore = 1234567890, Accuracy = 1, }, - new APIScore + new APIScoreInfo { User = new User { @@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual TotalScore = 1234789, Accuracy = 0.9997, }, - new APIScore + new APIScoreInfo { User = new User { @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual TotalScore = 12345678, Accuracy = 0.9854, }, - new APIScore + new APIScoreInfo { User = new User { @@ -144,7 +144,7 @@ namespace osu.Game.Tests.Visual TotalScore = 1234567, Accuracy = 0.8765, }, - new APIScore + new APIScoreInfo { User = new User { @@ -170,7 +170,7 @@ namespace osu.Game.Tests.Visual anotherScores = new[] { - new APIScore + new APIScoreInfo { User = new User { @@ -192,7 +192,7 @@ namespace osu.Game.Tests.Visual TotalScore = 1234789, Accuracy = 0.9997, }, - new APIScore + new APIScoreInfo { User = new User { @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual TotalScore = 1234567890, Accuracy = 1, }, - new APIScore + new APIScoreInfo { User = new User { @@ -231,7 +231,7 @@ namespace osu.Game.Tests.Visual TotalScore = 123456, Accuracy = 0.6543, }, - new APIScore + new APIScoreInfo { User = new User { @@ -252,7 +252,7 @@ namespace osu.Game.Tests.Visual TotalScore = 12345678, Accuracy = 0.9854, }, - new APIScore + new APIScoreInfo { User = new User { @@ -280,7 +280,7 @@ namespace osu.Game.Tests.Visual s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); } - topScore = new APIScore + topScoreInfo = new APIScoreInfo { User = new User { @@ -302,9 +302,9 @@ namespace osu.Game.Tests.Visual TotalScore = 987654321, Accuracy = 0.8487, }; - topScore.Statistics.Add(HitResult.Great, RNG.Next(2000)); - topScore.Statistics.Add(HitResult.Good, RNG.Next(2000)); - topScore.Statistics.Add(HitResult.Meh, RNG.Next(2000)); + topScoreInfo.Statistics.Add(HitResult.Great, RNG.Next(2000)); + topScoreInfo.Statistics.Add(HitResult.Good, RNG.Next(2000)); + topScoreInfo.Statistics.Add(HitResult.Meh, RNG.Next(2000)); } [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index d03a7dd889..f7630f0902 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual { var scores = new[] { - new Score + new ScoreInfo { Rank = ScoreRank.XH, Accuracy = 1, @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.X, Accuracy = 1, @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.SH, Accuracy = 1, @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.S, Accuracy = 1, @@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.A, Accuracy = 1, @@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.B, Accuracy = 0.9826, @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.C, Accuracy = 0.9654, @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.F, Accuracy = 0.6025, @@ -202,7 +202,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.F, Accuracy = 0.5140, @@ -220,7 +220,7 @@ namespace osu.Game.Tests.Visual }, }, }, - new Score + new ScoreInfo { Rank = ScoreRank.F, Accuracy = 0.4222, diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index 62ab89db3c..dfe1cdbfb0 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { - typeof(Score), + typeof(ScoreInfo), typeof(Results), typeof(ResultsPage), typeof(ResultsPageScore), @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - Add(new Results(new Score + Add(new Results(new ScoreInfo { TotalScore = 2845370, Accuracy = 0.98, diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index b823ea8b28..453e0271e2 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -28,7 +28,7 @@ namespace osu.Game.Database public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } public DbSet SkinInfo { get; set; } - public DbSet ScoreInfo { get; set; } + public DbSet ScoreInfo { get; set; } private readonly string connectionString; diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 3be5b91a0d..99207dccc6 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -33,7 +33,7 @@ namespace osu.Game.Online.API.Requests private void onSuccess(APIScores r) { - foreach (APIScore score in r.Scores) + foreach (APIScoreInfo score in r.Scores) score.ApplyBeatmap(beatmap); } diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 4d4aa4d957..12d70ea327 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -6,7 +6,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetUserScoresRequest : APIRequest> + public class GetUserScoresRequest : APIRequest> { private readonly long userId; private readonly ScoreType type; diff --git a/osu.Game/Online/API/Requests/Responses/APIScore.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs similarity index 98% rename from osu.Game/Online/API/Requests/Responses/APIScore.cs rename to osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 938cdbf98a..bea0c94920 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -14,7 +14,7 @@ using osu.Game.Users; namespace osu.Game.Online.API.Requests.Responses { - public class APIScore : Score + public class APIScoreInfo : ScoreInfo { [JsonProperty(@"score")] private double totalScore diff --git a/osu.Game/Online/API/Requests/Responses/APIScores.cs b/osu.Game/Online/API/Requests/Responses/APIScores.cs index b4213db253..ccffa3f9ed 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScores.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScores.cs @@ -9,6 +9,6 @@ namespace osu.Game.Online.API.Requests.Responses public class APIScores { [JsonProperty(@"scores")] - public IEnumerable Scores; + public IEnumerable Scores; } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c6112aadb8..2600d4f814 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -248,7 +248,7 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); - protected void LoadScore(Score score) + protected void LoadScore(ScoreInfo scoreInfo) { scoreLoad?.Cancel(); @@ -256,18 +256,18 @@ namespace osu.Game if (menu == null) { - scoreLoad = Schedule(() => LoadScore(score)); + scoreLoad = Schedule(() => LoadScore(scoreInfo)); return; } if (!menu.IsCurrentScreen) { menu.MakeCurrent(); - this.Delay(500).Schedule(() => LoadScore(score), out scoreLoad); + this.Delay(500).Schedule(() => LoadScore(scoreInfo), out scoreLoad); return; } - if (score.BeatmapInfo == null) + if (scoreInfo.BeatmapInfo == null) { notifications.Post(new SimpleNotification { @@ -277,12 +277,12 @@ namespace osu.Game return; } - ruleset.Value = score.Ruleset; + ruleset.Value = scoreInfo.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.BeatmapInfo); - Beatmap.Value.Mods.Value = score.Mods; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(scoreInfo.BeatmapInfo); + Beatmap.Value.Mods.Value = scoreInfo.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(scoreInfo.Replay))); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index b172954c43..1b079f33ea 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; - public DrawableScore(int index, APIScore score) + public DrawableScore(int index, APIScoreInfo scoreInfo) { ScoreModsContainer modsContainer; @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Font = @"Exo2.0-RegularItalic", Margin = new MarginPadding { Left = side_margin } }, - new DrawableFlag(score.User.Country) + new DrawableFlag(scoreInfo.User.Country) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - User = score.User, + User = scoreInfo.User, Margin = new MarginPadding { Left = 100 } }, modsContainer = new ScoreModsContainer @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = 0.42f }, - new DrawableRank(score.Rank) + new DrawableRank(scoreInfo.Rank) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, - Text = $@"{score.TotalScore:N0}", + Text = $@"{scoreInfo.TotalScore:N0}", Font = @"Venera", RelativePositionAxes = Axes.X, X = 0.75f, @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, - Text = $@"{score.Accuracy:P2}", + Text = $@"{scoreInfo.Accuracy:P2}", Font = @"Exo2.0-RegularItalic", RelativePositionAxes = Axes.X, X = 0.85f @@ -105,13 +105,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}", + Text = $"{scoreInfo.Statistics[HitResult.Great]}/{scoreInfo.Statistics[HitResult.Good]}/{scoreInfo.Statistics[HitResult.Meh]}", Font = @"Exo2.0-RegularItalic", Margin = new MarginPadding { Right = side_margin } }, }; - foreach (Mod mod in score.Mods) + foreach (Mod mod in scoreInfo.Mods) modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 4adca78072..b5e008d5da 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -43,26 +43,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly InfoColumn statistics; private readonly ScoreModsContainer modsContainer; - private APIScore score; - public APIScore Score + private APIScoreInfo scoreInfo; + public APIScoreInfo ScoreInfo { - get { return score; } + get { return scoreInfo; } set { - if (score == value) return; - score = value; + if (scoreInfo == value) return; + scoreInfo = value; - avatar.User = username.User = score.User; - flag.Country = score.User.Country; - date.Text = $@"achieved {score.Date:MMM d, yyyy}"; - rank.UpdateRank(score.Rank); + avatar.User = username.User = scoreInfo.User; + flag.Country = scoreInfo.User.Country; + date.Text = $@"achieved {scoreInfo.Date:MMM d, yyyy}"; + rank.UpdateRank(scoreInfo.Rank); - totalScore.Value = $@"{score.TotalScore:N0}"; - accuracy.Value = $@"{score.Accuracy:P2}"; - statistics.Value = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}"; + totalScore.Value = $@"{scoreInfo.TotalScore:N0}"; + accuracy.Value = $@"{scoreInfo.Accuracy:P2}"; + statistics.Value = $"{scoreInfo.Statistics[HitResult.Great]}/{scoreInfo.Statistics[HitResult.Good]}/{scoreInfo.Statistics[HitResult.Meh]}"; modsContainer.Clear(); - foreach (Mod mod in score.Mods) + foreach (Mod mod in scoreInfo.Mods) modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 38107c047d..f2ffea9ae6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -29,10 +29,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); } - private IEnumerable scores; + private IEnumerable scores; private BeatmapInfo beatmap; - public IEnumerable Scores + public IEnumerable Scores { get { return scores; } set @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } - topScore.Score = scores.FirstOrDefault(); + topScore.ScoreInfo = scores.FirstOrDefault(); topScore.Show(); flow.Clear(); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index a6e81f0e3b..a4f05b0f96 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -13,8 +13,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly double? weight; - public DrawablePerformanceScore(Score score, double? weight = null) - : base(score) + public DrawablePerformanceScore(ScoreInfo scoreInfo, double? weight = null) + : base(scoreInfo) { this.weight = weight; } @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks [BackgroundDependencyLoader] private void load(OsuColour colour) { - double pp = Score.PP ?? 0; + double pp = ScoreInfo.PP ?? 0; RightFlowContainer.Add(new OsuSpriteText { Text = $"{pp:0}pp", diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index b3251bba1d..a74d6ca35e 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -16,11 +16,11 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks public abstract class DrawableProfileScore : DrawableProfileRow { private readonly ScoreModsContainer modsContainer; - protected readonly Score Score; + protected readonly ScoreInfo ScoreInfo; - protected DrawableProfileScore(Score score) + protected DrawableProfileScore(ScoreInfo scoreInfo) { - Score = score; + ScoreInfo = scoreInfo; RelativeSizeAxes = Axes.X; Height = 60; @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { var text = new OsuSpriteText { - Text = $"accuracy: {Score.Accuracy:P2}", + Text = $"accuracy: {ScoreInfo.Accuracy:P2}", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, @@ -53,14 +53,14 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RightFlowContainer.Add(text); RightFlowContainer.SetLayoutPosition(text, 1); - LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.BeatmapInfo)); - LeftFlowContainer.Add(new DrawableDate(Score.Date)); + LeftFlowContainer.Add(new BeatmapMetadataContainer(ScoreInfo.BeatmapInfo)); + LeftFlowContainer.Add(new DrawableDate(ScoreInfo.Date)); - foreach (Mod mod in Score.Mods) + foreach (Mod mod in ScoreInfo.Mods) modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) }); } - protected override Drawable CreateLeftVisual() => new DrawableRank(Score.Rank) + protected override Drawable CreateLeftVisual() => new DrawableRank(ScoreInfo.Rank) { RelativeSizeAxes = Axes.Y, Width = 60, diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index 039b00e3b1..268ba57b75 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -10,8 +10,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { public class DrawableTotalScore : DrawableProfileScore { - public DrawableTotalScore(Score score) - : base(score) + public DrawableTotalScore(ScoreInfo scoreInfo) + : base(scoreInfo) { } @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { RightFlowContainer.Add(new OsuSpriteText { - Text = Score.TotalScore.ToString("#,###"), + Text = ScoreInfo.TotalScore.ToString("#,###"), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, TextSize = 18, diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index ed82c62e5c..3c0c810fce 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks MissingText.Hide(); - foreach (APIScore score in scores) + foreach (APIScoreInfo score in scores) { DrawableProfileScore drawableScore; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index d1ebb39f0f..8b1a54fc7c 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -17,21 +17,21 @@ namespace osu.Game.Rulesets.Difficulty protected readonly Ruleset Ruleset; protected readonly IBeatmap Beatmap; - protected readonly Score Score; + protected readonly ScoreInfo ScoreInfo; protected double TimeRate { get; private set; } = 1; - protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) + protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) { Ruleset = ruleset; - Score = score; + ScoreInfo = scoreInfo; - beatmap.Mods.Value = score.Mods; + beatmap.Mods.Value = scoreInfo.Mods; Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); - Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods); + Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(scoreInfo.Mods); - ApplyMods(score.Mods); + ApplyMods(scoreInfo.Mods); } protected virtual void ApplyMods(Mod[] mods) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 3f3cab5854..70d31c8480 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer where T : HitObject { - protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; + protected virtual ScoreInfo CreateReplayScore(Beatmap beatmap) => new ScoreInfo { Replay = new Replay() }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index a161a0a5e4..86bd6d9072 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets public abstract DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap); - public virtual PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => null; + public virtual PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => null; public virtual HitObjectComposer CreateHitObjectComposer() => null; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 23162a1b37..632ebcec6b 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -158,15 +158,15 @@ namespace osu.Game.Rulesets.Scoring /// /// Retrieve a score populated with data for the current play this processor is responsible for. /// - public virtual void PopulateScore(Score score) + public virtual void PopulateScore(ScoreInfo scoreInfo) { - score.TotalScore = TotalScore; - score.Combo = Combo; - score.MaxCombo = HighestCombo; - score.Accuracy = Accuracy; - score.Rank = Rank; - score.Date = DateTimeOffset.Now; - score.Health = Health; + scoreInfo.TotalScore = TotalScore; + scoreInfo.Combo = Combo; + scoreInfo.MaxCombo = HighestCombo; + scoreInfo.Accuracy = Accuracy; + scoreInfo.Rank = Rank; + scoreInfo.Date = DateTimeOffset.Now; + scoreInfo.Health = Health; } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index ab795bb900..1e65218af3 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -22,22 +22,22 @@ namespace osu.Game.Scoring.Legacy private IBeatmap currentBeatmap; private Ruleset currentRuleset; - public Score Parse(Stream stream) + public ScoreInfo Parse(Stream stream) { - Score score; + ScoreInfo scoreInfo; using (SerializationReader sr = new SerializationReader(stream)) { currentRuleset = GetRuleset(sr.ReadByte()); - score = new Score { Ruleset = currentRuleset.RulesetInfo }; + scoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo }; var version = sr.ReadInt32(); currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; - score.BeatmapInfo = currentBeatmap.BeatmapInfo; + scoreInfo.BeatmapInfo = currentBeatmap.BeatmapInfo; - score.User = new User { Username = sr.ReadString() }; - score.MD5Hash = sr.ReadString(); + scoreInfo.User = new User { Username = sr.ReadString() }; + scoreInfo.MD5Hash = sr.ReadString(); var count300 = sr.ReadUInt16(); var count100 = sr.ReadUInt16(); @@ -46,57 +46,57 @@ namespace osu.Game.Scoring.Legacy var countKatu = sr.ReadUInt16(); var countMiss = sr.ReadUInt16(); - score.Statistics[HitResult.Great] = count300; - score.Statistics[HitResult.Good] = count100; - score.Statistics[HitResult.Meh] = count50; - score.Statistics[HitResult.Perfect] = countGeki; - score.Statistics[HitResult.Ok] = countKatu; - score.Statistics[HitResult.Miss] = countMiss; + scoreInfo.Statistics[HitResult.Great] = count300; + scoreInfo.Statistics[HitResult.Good] = count100; + scoreInfo.Statistics[HitResult.Meh] = count50; + scoreInfo.Statistics[HitResult.Perfect] = countGeki; + scoreInfo.Statistics[HitResult.Ok] = countKatu; + scoreInfo.Statistics[HitResult.Miss] = countMiss; - score.TotalScore = sr.ReadInt32(); - score.MaxCombo = sr.ReadUInt16(); + scoreInfo.TotalScore = sr.ReadInt32(); + scoreInfo.MaxCombo = sr.ReadUInt16(); /* score.Perfect = */ sr.ReadBoolean(); - score.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); + scoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); /* score.HpGraphString = */ sr.ReadString(); - score.Date = sr.ReadDateTime(); + scoreInfo.Date = sr.ReadDateTime(); var compressedReplay = sr.ReadByteArray(); if (version >= 20140721) - score.OnlineScoreID = sr.ReadInt64(); + scoreInfo.OnlineScoreID = sr.ReadInt64(); else if (version >= 20121008) - score.OnlineScoreID = sr.ReadInt32(); + scoreInfo.OnlineScoreID = sr.ReadInt32(); - switch (score.Ruleset.ID) + switch (scoreInfo.Ruleset.ID) { case 0: { int totalHits = count50 + count100 + count300 + countMiss; - score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; + scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; break; } case 1: { int totalHits = count50 + count100 + count300 + countMiss; - score.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; + scoreInfo.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; break; } case 2: { int totalHits = count50 + count100 + count300 + countMiss + countKatu; - score.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; + scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; break; } case 3: { int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; - score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; + scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; break; } } @@ -120,13 +120,13 @@ namespace osu.Game.Scoring.Legacy using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) { - score.Replay = new Replay { User = score.User }; - readLegacyReplay(score.Replay, reader); + scoreInfo.Replay = new Replay { User = scoreInfo.User }; + readLegacyReplay(scoreInfo.Replay, reader); } } } - return score; + return scoreInfo; } private void readLegacyReplay(Replay replay, StreamReader reader) diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/ScoreInfo.cs similarity index 96% rename from osu.Game/Scoring/Score.cs rename to osu.Game/Scoring/ScoreInfo.cs index 0e894200b5..84657a729d 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -17,7 +17,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring { - public class Score : IHasFiles, IHasPrimaryKey, ISoftDelete + public class ScoreInfo : IHasFiles, IHasPrimaryKey, ISoftDelete { [JsonIgnore] public int ID { get; set; } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 08c8047078..b9c77288ff 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -15,7 +15,7 @@ using osu.Game.Scoring.Legacy; namespace osu.Game.Scoring { - public class ScoreManager : ArchiveModelManager + public class ScoreManager : ArchiveModelManager { public override string[] HandledExtensions => new[] { ".osr" }; @@ -35,7 +35,7 @@ namespace osu.Game.Scoring scores = (ScoreStore)ModelStore; } - protected override Score CreateModel(ArchiveReader archive) + protected override ScoreInfo CreateModel(ArchiveReader archive) { if (archive == null) return null; @@ -44,7 +44,7 @@ namespace osu.Game.Scoring return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream); } - protected override Score CheckForExisting(Score model) + protected override ScoreInfo CheckForExisting(ScoreInfo model) { var existingHashMatch = scores.ConsumableItems.FirstOrDefault(s => s.MD5Hash == model.MD5Hash); if (existingHashMatch != null) @@ -56,8 +56,8 @@ namespace osu.Game.Scoring return null; } - public List GetAllScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + public List GetAllScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); - public Score Query(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); + public ScoreInfo Query(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); } } diff --git a/osu.Game/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs index 781b5c3755..0d32e2ebc7 100644 --- a/osu.Game/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -8,14 +8,14 @@ using osu.Game.Database; namespace osu.Game.Scoring { - public class ScoreStore : MutableDatabaseBackedStore + public class ScoreStore : MutableDatabaseBackedStore { public ScoreStore(IDatabaseContextFactory factory, Storage storage) : base(factory, storage) { } - protected override IQueryable AddIncludesForConsumption(IQueryable query) + protected override IQueryable AddIncludesForConsumption(IQueryable query) => base.AddIncludesForConsumption(query).Include(s => s.Files).ThenInclude(f => f.FileInfo); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 49b71b4766..fe649ae35b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -273,7 +273,7 @@ namespace osu.Game.Screens.Play { if (!IsCurrentScreen) return; - var score = new Score + var score = new ScoreInfo { BeatmapInfo = Beatmap.Value.BeatmapInfo, Ruleset = ruleset diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index cd952c9ca2..89674c1ed0 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Ranking { public class Results : OsuScreen { - private readonly Score score; + private readonly ScoreInfo scoreInfo; private Container circleOuterBackground; private Container circleOuter; private Container circleInner; @@ -44,9 +44,9 @@ namespace osu.Game.Screens.Ranking private const float circle_outer_scale = 0.96f; - public Results(Score score) + public Results(ScoreInfo scoreInfo) { - this.score = score; + this.scoreInfo = scoreInfo; } private const float transition_time = 800; @@ -188,7 +188,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{score.MaxCombo}x", + Text = $"{scoreInfo.MaxCombo}x", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -209,7 +209,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{score.Accuracy:P2}", + Text = $"{scoreInfo.Accuracy:P2}", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -274,10 +274,10 @@ namespace osu.Game.Screens.Ranking switch (mode) { case ResultMode.Summary: - currentPage = new ResultsPageScore(score, Beatmap.Value); + currentPage = new ResultsPageScore(scoreInfo, Beatmap.Value); break; case ResultMode.Ranking: - currentPage = new ResultsPageRanking(score, Beatmap.Value); + currentPage = new ResultsPageRanking(scoreInfo, Beatmap.Value); break; } diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index d6b711230c..eb09ceb574 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -16,16 +16,16 @@ namespace osu.Game.Screens.Ranking { public class ResultsPage : Container { - protected readonly Score Score; + protected readonly ScoreInfo ScoreInfo; protected readonly WorkingBeatmap Beatmap; private CircularContainer content; private Box fill; protected override Container Content => content; - public ResultsPage(Score score, WorkingBeatmap beatmap) + public ResultsPage(ScoreInfo scoreInfo, WorkingBeatmap beatmap) { - Score = score; + ScoreInfo = scoreInfo; Beatmap = beatmap; RelativeSizeAxes = Axes.Both; } diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index 397b1a5905..235aa632cd 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Ranking { public class ResultsPageRanking : ResultsPage { - public ResultsPageRanking(Score score, WorkingBeatmap beatmap = null) : base(score, beatmap) + public ResultsPageRanking(ScoreInfo scoreInfo, WorkingBeatmap beatmap = null) : base(scoreInfo, beatmap) { } @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.Centre, Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Beatmap = Beatmap.BeatmapInfo ?? Score.BeatmapInfo, + Beatmap = Beatmap.BeatmapInfo ?? ScoreInfo.BeatmapInfo, Scale = new Vector2(0.7f) } }; diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index f4a4ff14bf..6641ccaf8c 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking private Container scoreContainer; private ScoreCounter scoreCounter; - public ResultsPageScore(Score score, WorkingBeatmap beatmap) : base(score, beatmap) { } + public ResultsPageScore(ScoreInfo scoreInfo, WorkingBeatmap beatmap) : base(scoreInfo, beatmap) { } private FillFlowContainer statisticsContainer; @@ -64,14 +64,14 @@ namespace osu.Game.Screens.Ranking Direction = FillDirection.Vertical, Children = new Drawable[] { - new UserHeader(Score.User) + new UserHeader(ScoreInfo.User) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = user_header_height, }, - new DrawableRank(Score.Rank) + new DrawableRank(ScoreInfo.Rank) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.TopCentre, Margin = new MarginPadding { Bottom = 10 }, }, - new DateTimeDisplay(Score.Date.LocalDateTime) + new DateTimeDisplay(ScoreInfo.Date.LocalDateTime) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -166,7 +166,7 @@ namespace osu.Game.Screens.Ranking } }; - statisticsContainer.ChildrenEnumerable = Score.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s)); + statisticsContainer.ChildrenEnumerable = ScoreInfo.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s)); } protected override void LoadComplete() @@ -175,7 +175,7 @@ namespace osu.Game.Screens.Ranking Schedule(() => { - scoreCounter.Increment(Score.TotalScore); + scoreCounter.Increment(ScoreInfo.TotalScore); int delay = 0; foreach (var s in statisticsContainer.Children) diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 4023353caf..2b94c11bf9 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select.Leaderboards private readonly IBindable ruleset = new Bindable(); - public Action ScoreSelected; + public Action ScoreSelected; private readonly LoadingAnimation loading; @@ -42,9 +42,9 @@ namespace osu.Game.Screens.Select.Leaderboards private bool scoresLoadedOnce; - private IEnumerable scores; + private IEnumerable scores; - public IEnumerable Scores + public IEnumerable Scores { get { return scores; } set diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 32bc7e42b6..4356deeb94 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Select.Leaderboards public static readonly float HEIGHT = 60; public readonly int RankPosition; - public readonly Score Score; + public readonly ScoreInfo ScoreInfo; private const float corner_radius = 5; private const float edge_margin = 5; @@ -43,9 +43,9 @@ namespace osu.Game.Screens.Select.Leaderboards private Container flagBadgeContainer; private FillFlowContainer modsContainer; - public LeaderboardScore(Score score, int rank) + public LeaderboardScore(ScoreInfo scoreInfo, int rank) { - Score = score; + ScoreInfo = scoreInfo; RankPosition = rank; RelativeSizeAxes = Axes.X; @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new[] { avatar = new DelayedLoadWrapper( - new Avatar(Score.User) + new Avatar(ScoreInfo.User) { RelativeSizeAxes = Axes.Both, CornerRadius = corner_radius, @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Select.Leaderboards { nameLabel = new OsuSpriteText { - Text = Score.User.Username, + Text = ScoreInfo.User.Username, Font = @"Exo2.0-BoldItalic", TextSize = 23, }, @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Select.Leaderboards Masking = true, Children = new Drawable[] { - new DrawableFlag(Score.User?.Country) + new DrawableFlag(ScoreInfo.User?.Country) { Width = 30, RelativeSizeAxes = Axes.Y, @@ -166,8 +166,8 @@ namespace osu.Game.Screens.Select.Leaderboards Margin = new MarginPadding { Left = edge_margin }, Children = new Drawable[] { - maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, Score.MaxCombo.ToString(), "Max Combo"), - accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(Score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", Score.Accuracy), "Accuracy"), + maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, ScoreInfo.MaxCombo.ToString(), "Max Combo"), + accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(ScoreInfo.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", ScoreInfo.Accuracy), "Accuracy"), }, }, }, @@ -183,13 +183,13 @@ namespace osu.Game.Screens.Select.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(Score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText(ScoreInfo.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), new Container { Size = new Vector2(40f, 20f), Children = new[] { - scoreRank = new DrawableRank(Score.Rank) + scoreRank = new DrawableRank(ScoreInfo.Rank) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -205,7 +205,7 @@ namespace osu.Game.Screens.Select.Leaderboards Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = Score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) + ChildrenEnumerable = ScoreInfo.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, }, From b8e60afa6961b0851b557dbab77808468a65d2a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 18:45:17 +0900 Subject: [PATCH 28/76] Move replays to an wrapping Score class --- .../Mods/CatchModAutoplay.cs | 11 ++-- .../Mods/ManiaModAutoplay.cs | 11 ++-- osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 9 +-- .../Mods/TaikoModAutoplay.cs | 11 ++-- .../API/Requests/Responses/APIScoreInfo.cs | 7 --- osu.Game/OsuGame.cs | 2 +- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 57 ++++++++++--------- osu.Game/Scoring/LegacyDatabasedScore.cs | 25 ++++++++ osu.Game/Scoring/Score.cs | 13 +++++ osu.Game/Scoring/ScoreInfo.cs | 4 -- osu.Game/Scoring/ScoreManager.cs | 6 +- 12 files changed, 88 insertions(+), 70 deletions(-) create mode 100644 osu.Game/Scoring/LegacyDatabasedScore.cs create mode 100644 osu.Game/Scoring/Score.cs diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 2b8324d327..8bba73ed64 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -12,13 +12,10 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModAutoplay : ModAutoplay { - protected override ScoreInfo CreateReplayScore(Beatmap beatmap) + protected override Score CreateReplayScore(Beatmap beatmap) => new Score { - return new ScoreInfo - { - User = new User { Username = "osu!salad!" }, - Replay = new CatchAutoGenerator(beatmap).Generate(), - }; - } + ScoreInfo = new ScoreInfo { User = new User { Username = "osu!salad!" } }, + Replay = new CatchAutoGenerator(beatmap).Generate(), + }; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 1629a3916d..f53943ec85 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -13,13 +13,10 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModAutoplay : ModAutoplay { - protected override ScoreInfo CreateReplayScore(Beatmap beatmap) + protected override Score CreateReplayScore(Beatmap beatmap) => new Score { - return new ScoreInfo - { - User = new User { Username = "osu!topus!" }, - Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), - }; - } + ScoreInfo = new ScoreInfo { User = new User { Username = "osu!topus!" } }, + Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), + }; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index c998f36792..ce5d3dae44 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -15,12 +15,9 @@ namespace osu.Game.Rulesets.Osu.Mods { public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray(); - protected override ScoreInfo CreateReplayScore(Beatmap beatmap) + protected override Score CreateReplayScore(Beatmap beatmap) => new Score { - return new ScoreInfo - { - Replay = new OsuAutoGenerator(beatmap).Generate() - }; - } + Replay = new OsuAutoGenerator(beatmap).Generate() + }; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index ff64ecf1bd..62111ae74a 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -12,13 +12,10 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModAutoplay : ModAutoplay { - protected override ScoreInfo CreateReplayScore(Beatmap beatmap) + protected override Score CreateReplayScore(Beatmap beatmap) => new Score { - return new ScoreInfo - { - User = new User { Username = "mekkadosu!" }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; - } + ScoreInfo = new ScoreInfo { User = new User { Username = "mekkadosu!" } }, + Replay = new TaikoAutoGenerator(beatmap).Generate(), + }; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index bea0c94920..19f8206667 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -34,12 +33,6 @@ namespace osu.Game.Online.API.Requests.Responses set => User = value; } - [JsonProperty(@"replay_data")] - private Replay replay - { - set => Replay = value; - } - [JsonProperty(@"mode_int")] public int OnlineRulesetID { get; set; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2600d4f814..9d22ecc220 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -282,7 +282,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(scoreInfo.BeatmapInfo); Beatmap.Value.Mods.Value = scoreInfo.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(scoreInfo.Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(scoreInfo).Replay))); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 70d31c8480..3f3cab5854 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer where T : HitObject { - protected virtual ScoreInfo CreateReplayScore(Beatmap beatmap) => new ScoreInfo { Replay = new Replay() }; + protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 1e65218af3..f17873df89 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -22,22 +22,26 @@ namespace osu.Game.Scoring.Legacy private IBeatmap currentBeatmap; private Ruleset currentRuleset; - public ScoreInfo Parse(Stream stream) + public Score Parse(Stream stream) { - ScoreInfo scoreInfo; + var score = new Score + { + ScoreInfo = new ScoreInfo(), + Replay = new Replay() + }; using (SerializationReader sr = new SerializationReader(stream)) { currentRuleset = GetRuleset(sr.ReadByte()); - scoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo }; + score.ScoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo }; var version = sr.ReadInt32(); currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; - scoreInfo.BeatmapInfo = currentBeatmap.BeatmapInfo; + score.ScoreInfo.BeatmapInfo = currentBeatmap.BeatmapInfo; - scoreInfo.User = new User { Username = sr.ReadString() }; - scoreInfo.MD5Hash = sr.ReadString(); + score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; + score.ScoreInfo.MD5Hash = sr.ReadString(); var count300 = sr.ReadUInt16(); var count100 = sr.ReadUInt16(); @@ -46,57 +50,57 @@ namespace osu.Game.Scoring.Legacy var countKatu = sr.ReadUInt16(); var countMiss = sr.ReadUInt16(); - scoreInfo.Statistics[HitResult.Great] = count300; - scoreInfo.Statistics[HitResult.Good] = count100; - scoreInfo.Statistics[HitResult.Meh] = count50; - scoreInfo.Statistics[HitResult.Perfect] = countGeki; - scoreInfo.Statistics[HitResult.Ok] = countKatu; - scoreInfo.Statistics[HitResult.Miss] = countMiss; + score.ScoreInfo.Statistics[HitResult.Great] = count300; + score.ScoreInfo.Statistics[HitResult.Good] = count100; + score.ScoreInfo.Statistics[HitResult.Meh] = count50; + score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki; + score.ScoreInfo.Statistics[HitResult.Ok] = countKatu; + score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; - scoreInfo.TotalScore = sr.ReadInt32(); - scoreInfo.MaxCombo = sr.ReadUInt16(); + score.ScoreInfo.TotalScore = sr.ReadInt32(); + score.ScoreInfo.MaxCombo = sr.ReadUInt16(); /* score.Perfect = */ sr.ReadBoolean(); - scoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); + score.ScoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); /* score.HpGraphString = */ sr.ReadString(); - scoreInfo.Date = sr.ReadDateTime(); + score.ScoreInfo.Date = sr.ReadDateTime(); var compressedReplay = sr.ReadByteArray(); if (version >= 20140721) - scoreInfo.OnlineScoreID = sr.ReadInt64(); + score.ScoreInfo.OnlineScoreID = sr.ReadInt64(); else if (version >= 20121008) - scoreInfo.OnlineScoreID = sr.ReadInt32(); + score.ScoreInfo.OnlineScoreID = sr.ReadInt32(); - switch (scoreInfo.Ruleset.ID) + switch (score.ScoreInfo.Ruleset.ID) { case 0: { int totalHits = count50 + count100 + count300 + countMiss; - scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; + score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; break; } case 1: { int totalHits = count50 + count100 + count300 + countMiss; - scoreInfo.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; + score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; break; } case 2: { int totalHits = count50 + count100 + count300 + countMiss + countKatu; - scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; + score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; break; } case 3: { int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; - scoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; + score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; break; } } @@ -119,14 +123,11 @@ namespace osu.Game.Scoring.Legacy using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) - { - scoreInfo.Replay = new Replay { User = scoreInfo.User }; - readLegacyReplay(scoreInfo.Replay, reader); - } + readLegacyReplay(score.Replay, reader); } } - return scoreInfo; + return score; } private void readLegacyReplay(Replay replay, StreamReader reader) diff --git a/osu.Game/Scoring/LegacyDatabasedScore.cs b/osu.Game/Scoring/LegacyDatabasedScore.cs new file mode 100644 index 0000000000..29996d5c01 --- /dev/null +++ b/osu.Game/Scoring/LegacyDatabasedScore.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.IO.Stores; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Scoring.Legacy; + +namespace osu.Game.Scoring +{ + public class LegacyDatabasedScore : Score + { + public LegacyDatabasedScore(ScoreInfo scoreInfo, RulesetStore rulesets, BeatmapManager beatmaps, IResourceStore store) + { + ScoreInfo = scoreInfo; + + var replayFilename = scoreInfo.Files.First(f => f.Filename.EndsWith(".osr", StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; + + using (var stream = store.GetStream(replayFilename)) + Replay = new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).Replay; + } + } +} diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs new file mode 100644 index 0000000000..ffbee920cb --- /dev/null +++ b/osu.Game/Scoring/Score.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Replays; + +namespace osu.Game.Scoring +{ + public class Score + { + public ScoreInfo ScoreInfo = new ScoreInfo(); + public Replay Replay = new Replay(); + } +} diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 84657a729d..9c4d196a04 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -9,7 +9,6 @@ using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.Replays; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; @@ -64,9 +63,6 @@ namespace osu.Game.Scoring set => User = new User { Username = value }; } - [JsonIgnore] - public Replay Replay; - public int BeatmapInfoID { get; set; } public BeatmapInfo BeatmapInfo; diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index b9c77288ff..eec23ba48c 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -41,7 +41,7 @@ namespace osu.Game.Scoring return null; using (var stream = archive.GetStream(archive.Filenames.First(f => f.EndsWith(".osr")))) - return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream); + return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).ScoreInfo; } protected override ScoreInfo CheckForExisting(ScoreInfo model) @@ -56,7 +56,9 @@ namespace osu.Game.Scoring return null; } - public List GetAllScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + public Score GetScore(ScoreInfo scoreInfo) => new LegacyDatabasedScore(scoreInfo, rulesets, beatmaps, Files.Store); + + public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); public ScoreInfo Query(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); } From 542a75d076f97b0e07f49c23440436d1570659d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 18:52:57 +0900 Subject: [PATCH 29/76] Add index on online score id --- osu.Game/Database/OsuDbContext.cs | 2 ++ osu.Game/Scoring/ScoreInfo.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 453e0271e2..7ffde8bf0e 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -119,6 +119,8 @@ namespace osu.Game.Database modelBuilder.Entity().HasIndex(b => b.ShortName).IsUnique(); modelBuilder.Entity().HasOne(b => b.BaseDifficulty); + + modelBuilder.Entity().HasIndex(b => b.OnlineScoreID).IsUnique(); } private class OsuDbLoggerFactory : ILoggerFactory diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 9c4d196a04..056bec1d8c 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring public BeatmapInfo BeatmapInfo; - public long OnlineScoreID; + public long? OnlineScoreID { get; set; } public DateTimeOffset Date; From ce660b6d67499f74908cc26f61a8431787c17be8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Nov 2018 19:01:22 +0900 Subject: [PATCH 30/76] Add skin de-duplication --- osu.Game/Beatmaps/BeatmapManager.cs | 14 +----- osu.Game/Database/ArchiveModelManager.cs | 6 +++ osu.Game/Database/IHasFiles.cs | 2 + osu.Game/Skinning/SkinInfo.cs | 6 ++- osu.Game/Skinning/SkinManager.cs | 64 +++++++++++------------- 5 files changed, 43 insertions(+), 49 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 24c68d392b..c4cbce6430 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -129,18 +129,8 @@ namespace osu.Game.Beatmaps beatmaps.ForEach(b => b.OnlineBeatmapID = null); } - protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model) - { - // check if this beatmap has already been imported and exit early if so - var existingHashMatch = beatmaps.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); - if (existingHashMatch != null) - { - Undelete(existingHashMatch); - return existingHashMatch; - } - - return null; - } + protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model) => + beatmaps.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); /// /// Downloads a beatmap. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3686b702c4..2d5cbac8f1 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -235,6 +235,7 @@ namespace osu.Game.Database if (existing != null) { + Undelete(existing); Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); return existing; } @@ -471,6 +472,11 @@ namespace osu.Game.Database { } + /// + /// Check whether an existing model already exists for a new import item. + /// + /// The new model proposed for import. Note that has not yet been run on this model. + /// An existing model which matches the criteria to skip importing, else null. protected virtual TModel CheckForExisting(TModel model) => null; private DbSet queryModel() => ContextFactory.Get().Set(); diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index 3aaba37efc..f6044cd7e5 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.cs @@ -14,5 +14,7 @@ namespace osu.Game.Database { List Files { get; set; } + + string Hash { get; set; } } } diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 47dad60d88..0014f8b3a0 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -15,16 +15,20 @@ namespace osu.Game.Skinning public string Name { get; set; } + public string Hash { get; set; } + public string Creator { get; set; } public List Files { get; set; } public bool DeletePending { get; set; } + public string FullName => $"\"{Name}\" by {Creator}"; + public static SkinInfo Default { get; } = new SkinInfo { Name = "osu!lazer", Creator = "team osu!" }; public bool Equals(SkinInfo other) => other != null && ID == other.ID; - public override string ToString() => $"\"{Name}\" by {Creator}"; + public override string ToString() => FullName; } } diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index bd694e443a..b41b424661 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -28,6 +28,28 @@ namespace osu.Game.Skinning protected override string ImportFromStablePath => "Skins"; + public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio) + : base(storage, contextFactory, new SkinStore(contextFactory, storage), importHost) + { + this.audio = audio; + + ItemRemoved += removedInfo => + { + // check the removed skin is not the current user choice. if it is, switch back to default. + if (removedInfo.ID == CurrentSkinInfo.Value.ID) + CurrentSkinInfo.Value = SkinInfo.Default; + }; + + CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = getSkin(info); + CurrentSkin.ValueChanged += skin => + { + if (skin.SkinInfo != CurrentSkinInfo.Value) + throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead."); + + SourceChanged?.Invoke(); + }; + } + /// /// Returns a list of all usable s. Includes the special default skin plus all skins from . /// @@ -45,24 +67,16 @@ namespace osu.Game.Skinning /// A list of available . public List GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); - protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo - { - Name = archive.Name - }; + protected override SkinInfo CheckForExisting(SkinInfo model) + => ModelStore.ConsumableItems.FirstOrDefault(s => s.Name == model.Name && s.Creator == model.Creator); + + protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; protected override void Populate(SkinInfo model, ArchiveReader archive) { base.Populate(model, archive); - populate(model); - } - /// - /// Populate a from its (if possible). - /// - /// - private void populate(SkinInfo model) - { - Skin reference = GetSkin(model); + Skin reference = getSkin(model); if (!string.IsNullOrEmpty(reference.Configuration.SkinInfo.Name)) { model.Name = reference.Configuration.SkinInfo.Name; @@ -80,7 +94,7 @@ namespace osu.Game.Skinning /// /// The skin to lookup. /// A instance correlating to the provided . - public Skin GetSkin(SkinInfo skinInfo) + private Skin getSkin(SkinInfo skinInfo) { if (skinInfo == SkinInfo.Default) return new DefaultSkin(); @@ -88,28 +102,6 @@ namespace osu.Game.Skinning return new LegacySkin(skinInfo, Files.Store, audio); } - public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio) - : base(storage, contextFactory, new SkinStore(contextFactory, storage), importHost) - { - this.audio = audio; - - ItemRemoved += removedInfo => - { - // check the removed skin is not the current user choice. if it is, switch back to default. - if (removedInfo.ID == CurrentSkinInfo.Value.ID) - CurrentSkinInfo.Value = SkinInfo.Default; - }; - - CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = GetSkin(info); - CurrentSkin.ValueChanged += skin => - { - if (skin.SkinInfo != CurrentSkinInfo.Value) - throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead."); - - SourceChanged?.Invoke(); - }; - } - /// /// Perform a lookup query on available s. /// From 0384f3549f8b65b69cb66ec68e17bb9accfa1de9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Nov 2018 19:15:56 +0900 Subject: [PATCH 31/76] Add hash and missing indices to SkinInfo --- osu.Game/Database/OsuDbContext.cs | 3 + ...20181128100659_AddSkinInfoHash.Designer.cs | 387 ++++++++++++++++++ .../20181128100659_AddSkinInfoHash.cs | 41 ++ .../Migrations/OsuDbContextModelSnapshot.cs | 9 +- 4 files changed, 439 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs create mode 100644 osu.Game/Migrations/20181128100659_AddSkinInfoHash.cs diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 20e144c033..0a5bcaaebe 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -105,6 +105,9 @@ namespace osu.Game.Database modelBuilder.Entity().HasIndex(b => b.DeletePending); modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); + modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); + modelBuilder.Entity().HasIndex(b => b.DeletePending); + modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); modelBuilder.Entity().HasIndex(b => b.IntAction); diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs new file mode 100644 index 0000000000..120674671a --- /dev/null +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs @@ -0,0 +1,387 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20181128100659_AddSkinInfoHash")] + partial class AddSkinInfoHash + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.cs new file mode 100644 index 0000000000..860264a7dd --- /dev/null +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.cs @@ -0,0 +1,41 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddSkinInfoHash : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Hash", + table: "SkinInfo", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_SkinInfo_DeletePending", + table: "SkinInfo", + column: "DeletePending"); + + migrationBuilder.CreateIndex( + name: "IX_SkinInfo_Hash", + table: "SkinInfo", + column: "Hash", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_SkinInfo_DeletePending", + table: "SkinInfo"); + + migrationBuilder.DropIndex( + name: "IX_SkinInfo_Hash", + table: "SkinInfo"); + + migrationBuilder.DropColumn( + name: "Hash", + table: "SkinInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 663676a6d3..105a3d40b9 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -311,10 +311,17 @@ namespace osu.Game.Migrations b.Property("DeletePending"); + b.Property("Hash"); + b.Property("Name"); b.HasKey("ID"); + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + b.ToTable("SkinInfo"); }); From ab2b2493a10df2d37c3ce45cabb634f4222aaba8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Nov 2018 19:16:05 +0900 Subject: [PATCH 32/76] Move hashing functionality to ArchiveModelManager --- osu.Game/Beatmaps/BeatmapManager.cs | 20 ++------------- osu.Game/Database/ArchiveModelManager.cs | 31 ++++++++++++++++++++++-- osu.Game/Skinning/SkinManager.cs | 5 ++-- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c4cbce6430..8728d776d0 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -63,6 +63,8 @@ namespace osu.Game.Beatmaps public override string[] HandledExtensions => new[] { ".osz" }; + protected override string[] HashableFileTypes => new[] { ".osu" }; + protected override string ImportFromStablePath => "Songs"; private readonly RulesetStore rulesets; @@ -129,9 +131,6 @@ namespace osu.Game.Beatmaps beatmaps.ForEach(b => b.OnlineBeatmapID = null); } - protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model) => - beatmaps.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); - /// /// Downloads a beatmap. /// This will post notifications tracking progress. @@ -307,20 +306,6 @@ namespace osu.Game.Beatmaps /// Results from the provided query. public IQueryable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); - /// - /// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content. - /// - private string computeBeatmapSetHash(ArchiveReader reader) - { - // for now, concatenate all .osu files in the set to create a unique hash. - MemoryStream hashable = new MemoryStream(); - foreach (string file in reader.Filenames.Where(f => f.EndsWith(".osu"))) - using (Stream s = reader.GetStream(file)) - s.CopyTo(hashable); - - return hashable.ComputeSHA2Hash(); - } - protected override BeatmapSetInfo CreateModel(ArchiveReader reader) { // let's make sure there are actually .osu files to import. @@ -339,7 +324,6 @@ namespace osu.Game.Beatmaps { OnlineBeatmapSetID = beatmap.BeatmapInfo.BeatmapSet?.OnlineBeatmapSetID, Beatmaps = new List(), - Hash = computeBeatmapSetHash(reader), Metadata = beatmap.Metadata, }; } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 2d5cbac8f1..e2157f5fb3 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; +using osu.Framework.Extensions; using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; @@ -203,7 +204,12 @@ namespace osu.Game.Database try { var model = CreateModel(archive); - return model == null ? null : Import(model, archive); + + if (model == null) return null; + + model.Hash = computeBeatmapSetHash(archive); + + return Import(model, archive); } catch (Exception e) { @@ -212,6 +218,27 @@ namespace osu.Game.Database } } + /// + /// Any file extensions which should be included in hash creation. + /// Generally should include all file types which determine the file's uniqueness. + /// Large files should be avoided if possible. + /// + protected abstract string[] HashableFileTypes { get; } + + /// + /// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content. + /// + private string computeBeatmapSetHash(ArchiveReader reader) + { + // for now, concatenate all .osu files in the set to create a unique hash. + MemoryStream hashable = new MemoryStream(); + foreach (string file in reader.Filenames.Where(f => f.EndsWith(".osu"))) + using (Stream s = reader.GetStream(file)) + s.CopyTo(hashable); + + return hashable.ComputeSHA2Hash(); + } + /// /// Import an item from a . /// @@ -477,7 +504,7 @@ namespace osu.Game.Database /// /// The new model proposed for import. Note that has not yet been run on this model. /// An existing model which matches the criteria to skip importing, else null. - protected virtual TModel CheckForExisting(TModel model) => null; + protected virtual TModel CheckForExisting(TModel model) => ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); private DbSet queryModel() => ContextFactory.Get().Set(); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index b41b424661..ce179d43ef 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -26,6 +26,8 @@ namespace osu.Game.Skinning public override string[] HandledExtensions => new[] { ".osk" }; + protected override string[] HashableFileTypes => new[] { ".ini" }; + protected override string ImportFromStablePath => "Skins"; public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost, AudioManager audio) @@ -67,9 +69,6 @@ namespace osu.Game.Skinning /// A list of available . public List GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); - protected override SkinInfo CheckForExisting(SkinInfo model) - => ModelStore.ConsumableItems.FirstOrDefault(s => s.Name == model.Name && s.Creator == model.Creator); - protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; protected override void Populate(SkinInfo model, ArchiveReader archive) From 554c858944303ba0d78a0309969c0864ec9f0fe5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 19:47:20 +0900 Subject: [PATCH 33/76] Fix mods not deserializing properly --- osu.Game/Scoring/ScoreInfo.cs | 38 +++++++++++++++-------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 056bec1d8c..860af64c62 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using JetBrains.Annotations; using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Database; @@ -39,22 +38,27 @@ namespace osu.Game.Scoring public RulesetInfo Ruleset { get; set; } - [NotMapped] - [JsonIgnore] - public Mod[] Mods { get; set; } = { }; + [NotMapped, JsonIgnore] + public Mod[] Mods + { + get + { + var deserialized = JsonConvert.DeserializeObject(modsString); + return Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d == mod.ShortenedName)).ToArray(); + } + set => modsString = JsonConvert.SerializeObject(value.Select(m => m.ShortenedName).ToArray()); + } + + [NotMapped, JsonIgnore] + private string modsString; public string ModsString { - get => JsonConvert.SerializeObject(Mods); - set - { - var deserialized = JsonConvert.DeserializeObject(value); - Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d.ShortenedName == mod.ShortenedName)).ToArray(); - } + get => modsString; + set => modsString = value; } - [NotMapped] - [JsonIgnore] + [NotMapped, JsonIgnore] public User User; public string UserString @@ -82,15 +86,5 @@ namespace osu.Game.Scoring public List Files { get; set; } public bool DeletePending { get; set; } - - [UsedImplicitly] - private class SerializableMod : Mod - { - public override string Name => ShortenedName; - - public override string ShortenedName { get; } = string.Empty; - - public override double ScoreMultiplier => 0; - } } } From 2bb7a078c9e55254d68930a514378cc08435996d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 19:48:15 +0900 Subject: [PATCH 34/76] Don't import replays with no existing beatmap --- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 14 +++++++++++++- osu.Game/Scoring/ScoreManager.cs | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index f17873df89..5a9a09cfbc 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -37,7 +37,11 @@ namespace osu.Game.Scoring.Legacy var version = sr.ReadInt32(); - currentBeatmap = GetBeatmap(sr.ReadString()).Beatmap; + var workingBeatmap = GetBeatmap(sr.ReadString()); + if (workingBeatmap is DummyWorkingBeatmap) + throw new BeatmapNotFoundException(); + + currentBeatmap = workingBeatmap.Beatmap; score.ScoreInfo.BeatmapInfo = currentBeatmap.BeatmapInfo; score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; @@ -185,5 +189,13 @@ namespace osu.Game.Scoring.Legacy /// The MD5 hash. /// The . protected abstract WorkingBeatmap GetBeatmap(string md5Hash); + + public class BeatmapNotFoundException : Exception + { + public BeatmapNotFoundException() + : base("No corresponding beatmap for the score could be found.") + { + } + } } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index eec23ba48c..dbd2f0588d 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Database; @@ -41,7 +42,17 @@ namespace osu.Game.Scoring return null; using (var stream = archive.GetStream(archive.Filenames.First(f => f.EndsWith(".osr")))) - return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).ScoreInfo; + { + try + { + return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).ScoreInfo; + } + catch (LegacyScoreParser.BeatmapNotFoundException e) + { + Logger.Log(e.Message, LoggingTarget.Information, LogLevel.Error); + return null; + } + } } protected override ScoreInfo CheckForExisting(ScoreInfo model) From aaf3e650a53b3f6e4ee2aeef4037f613f0c3a67e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 20:16:20 +0900 Subject: [PATCH 35/76] Fix some columns --- osu.Game/Scoring/ScoreInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 860af64c62..56ceb631fc 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -69,11 +69,11 @@ namespace osu.Game.Scoring public int BeatmapInfoID { get; set; } - public BeatmapInfo BeatmapInfo; + public BeatmapInfo BeatmapInfo { get; set; } public long? OnlineScoreID { get; set; } - public DateTimeOffset Date; + public DateTimeOffset Date { get; set; } public Dictionary Statistics = new Dictionary(); From a88b69ec4324ac6ae87d0f82eea7943c1dfb37af Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 20:19:21 +0900 Subject: [PATCH 36/76] Notify of existing imports --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 2 +- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 7 +++++-- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 7 +++++-- osu.Game/Overlays/MusicController.cs | 9 ++++++++- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 9 ++++++++- osu.Game/Screens/Select/SongSelect.cs | 2 +- 9 files changed, 31 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 616ba132fd..fb6f735d2d 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Beatmaps.IO int fireCount = 0; // ReSharper disable once AccessToModifiedClosure - manager.ItemAdded += _ => fireCount++; + manager.ItemAdded += (_, __) => fireCount++; manager.ItemRemoved += _ => fireCount++; var imported = loadOszIntoOsu(osu); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 160d081b8a..f1920b43cc 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps.Drawables } } - private void setAdded(BeatmapSetInfo s) => Schedule(() => + private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() => { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) DownloadState.Value = DownloadStatus.Downloaded; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 364a3945d2..ec87df3d71 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -31,6 +31,8 @@ namespace osu.Game.Database where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { + public delegate void ItemAddedDelegate(TModel model, bool existing); + /// /// Set an endpoint for notifications to be posted to. /// @@ -40,7 +42,7 @@ namespace osu.Game.Database /// Fired when a new becomes available in the database. /// This is not guaranteed to run on the update thread. /// - public event Action ItemAdded; + public event ItemAddedDelegate ItemAdded; /// /// Fired when a is removed from the database. @@ -107,7 +109,7 @@ namespace osu.Game.Database ContextFactory = contextFactory; ModelStore = modelStore; - ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s)); + ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s, false)); ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s)); Files = new FileStore(contextFactory, storage); @@ -236,6 +238,7 @@ namespace osu.Game.Database if (existing != null) { Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + handleEvent(() => ItemAdded?.Invoke(existing, true)); return existing; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9d22ecc220..eef384ba6f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -148,7 +148,7 @@ namespace osu.Game { this.frameworkConfig = frameworkConfig; - ScoreManager.ItemAdded += score => Schedule(() => LoadScore(score)); + ScoreManager.ItemAdded += (score, _) => Schedule(() => LoadScore(score)); if (!Host.IsPrimaryInstance) { diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 44f7b6d49c..5b98d92654 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -174,7 +174,7 @@ namespace osu.Game.Overlays.Direct }; } - private void setAdded(BeatmapSetInfo s) => Schedule(() => + private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() => { if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) progressBar.FadeOut(500); diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index ef7f946859..a2a835a259 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap) { - beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet); + beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false)); beatmaps.ItemAdded += addBeatmapSet; beatmaps.ItemRemoved += removeBeatmapSet; @@ -83,8 +83,11 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => + private void addBeatmapSet(BeatmapSetInfo obj, bool existing) => Schedule(() => { + if (existing) + return; + var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }; items.Add(newItem); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 58e03bd0cd..31fceebc93 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -214,7 +214,14 @@ namespace osu.Game.Overlays beatmapSets.Insert(index, beatmapSetInfo); } - private void handleBeatmapAdded(BeatmapSetInfo obj) => Schedule(() => beatmapSets.Add(obj)); + private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing) + { + if (existing) + return; + + Schedule(() => beatmapSets.Add(obj)); + } + private void handleBeatmapRemoved(BeatmapSetInfo obj) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == obj.ID)); protected override void LoadComplete() diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 938e2ca2c3..e03bf856c9 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -71,7 +71,14 @@ namespace osu.Game.Overlays.Settings.Sections } private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray()); - private void itemAdded(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Append(s).ToArray()); + + private void itemAdded(SkinInfo s, bool existing) + { + if (existing) + return; + + Schedule(() => skinDropdown.Items = skinDropdown.Items.Append(s).ToArray()); + } protected override void Dispose(bool isDisposing) { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ff897094ee..360032c37c 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -503,7 +503,7 @@ namespace osu.Game.Screens.Select } } - private void onBeatmapSetAdded(BeatmapSetInfo s) => Carousel.UpdateBeatmapSet(s); + private void onBeatmapSetAdded(BeatmapSetInfo s, bool existing) => Carousel.UpdateBeatmapSet(s); private void onBeatmapSetRemoved(BeatmapSetInfo s) => Carousel.RemoveBeatmapSet(s); private void onBeatmapRestored(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); private void onBeatmapHidden(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); From d2f0a921ca1e7c3b2b6bd12b88c7a5e7b89e6d01 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 28 Nov 2018 20:41:48 +0900 Subject: [PATCH 37/76] Fix lookups by beatmapinfo failing for imports of existing sores --- osu.Game/OsuGame.cs | 6 ++++-- osu.Game/Scoring/ScoreStore.cs | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index eef384ba6f..830cefc58c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -267,7 +267,9 @@ namespace osu.Game return; } - if (scoreInfo.BeatmapInfo == null) + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); + + if (databasedBeatmap == null) { notifications.Post(new SimpleNotification { @@ -279,7 +281,7 @@ namespace osu.Game ruleset.Value = scoreInfo.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(scoreInfo.BeatmapInfo); + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); Beatmap.Value.Mods.Value = scoreInfo.Mods; menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(scoreInfo).Replay))); diff --git a/osu.Game/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs index 0d32e2ebc7..eeef9894bf 100644 --- a/osu.Game/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -16,6 +16,9 @@ namespace osu.Game.Scoring } protected override IQueryable AddIncludesForConsumption(IQueryable query) - => base.AddIncludesForConsumption(query).Include(s => s.Files).ThenInclude(f => f.FileInfo); + => base.AddIncludesForConsumption(query) + .Include(s => s.Files).ThenInclude(f => f.FileInfo) + .Include(s => s.BeatmapInfo) + .Include(s => s.Ruleset); } } From a1666fb7fa2deea4b9a81f940440b5db1d209f1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:21:20 +0900 Subject: [PATCH 38/76] MouseDownPosition -> DragPosition --- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 12 ++++++------ .../Edit/ManiaSelectionHandler.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index df229b23ae..f190843f5d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class ManiaSelectionBlueprint : SelectionBlueprint { - public Vector2 ScreenSpaceMouseDownPosition { get; private set; } - public Vector2 MouseDownPosition { get; private set; } + public Vector2 ScreenSpaceDragPosition { get; private set; } + public Vector2 DragPosition { get; private set; } protected new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override bool OnMouseDown(MouseDownEvent e) { - ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; - MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; + DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); return base.OnMouseDown(e); } @@ -59,8 +59,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { var result = base.OnDrag(e); - ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; - MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; + DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); return result; } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 1d6b9d6c69..828f6d87bc 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit { var referenceParent = (HitObjectContainer)reference.HitObject.Parent; - float offsetFromReferenceOrigin = reference.MouseDownPosition.Y - reference.HitObject.OriginPosition.Y; - float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceMouseDownPosition).Y - offsetFromReferenceOrigin; + float offsetFromReferenceOrigin = reference.DragPosition.Y - reference.HitObject.OriginPosition.Y; + float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceDragPosition).Y - offsetFromReferenceOrigin; // Flip the vertical coordinate space when scrolling downwards if (scrollingInfo.Direction.Value == ScrollingDirection.Down) From aa7f66b24ad78145632a1c4e7ddaf8bef17c81e5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 18:29:25 +0900 Subject: [PATCH 39/76] Fix crash when loading scores with no mods --- osu.Game/Scoring/ScoreInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 56ceb631fc..1cc8e53574 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -43,6 +43,9 @@ namespace osu.Game.Scoring { get { + if (modsString == null) + return Array.Empty(); + var deserialized = JsonConvert.DeserializeObject(modsString); return Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d == mod.ShortenedName)).ToArray(); } From b673eb79b1a736bc52368cc3e1b88243e4c925a0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 18:29:58 +0900 Subject: [PATCH 40/76] Fix local score infos conflicting --- osu.Game/Scoring/ScoreManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index dbd2f0588d..5eedf3bcf8 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -57,7 +57,7 @@ namespace osu.Game.Scoring protected override ScoreInfo CheckForExisting(ScoreInfo model) { - var existingHashMatch = scores.ConsumableItems.FirstOrDefault(s => s.MD5Hash == model.MD5Hash); + var existingHashMatch = scores.ConsumableItems.FirstOrDefault(s => s.MD5Hash != null && s.MD5Hash == model.MD5Hash); if (existingHashMatch != null) { Undelete(existingHashMatch); From 55307365418b520bc566ff0f7b28d5a8b908026b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 14:24:10 +0900 Subject: [PATCH 41/76] Cleanup mods string --- osu.Game/Scoring/ScoreInfo.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 1cc8e53574..54284fa24b 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -43,23 +43,16 @@ namespace osu.Game.Scoring { get { - if (modsString == null) + if (ModsString == null) return Array.Empty(); - var deserialized = JsonConvert.DeserializeObject(modsString); + var deserialized = JsonConvert.DeserializeObject(ModsString); return Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d == mod.ShortenedName)).ToArray(); } - set => modsString = JsonConvert.SerializeObject(value.Select(m => m.ShortenedName).ToArray()); + set => ModsString = JsonConvert.SerializeObject(value.Select(m => m.ShortenedName).ToArray()); } - [NotMapped, JsonIgnore] - private string modsString; - - public string ModsString - { - get => modsString; - set => modsString = value; - } + public string ModsString { get; set; } [NotMapped, JsonIgnore] public User User; From 690a1f07655daf2c6e50122ebab41c1ce03f97a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 14:27:08 +0900 Subject: [PATCH 42/76] Fix score statistics not being serialised --- osu.Game/Scoring/ScoreInfo.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 54284fa24b..6f06f2400b 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -71,8 +71,21 @@ namespace osu.Game.Scoring public DateTimeOffset Date { get; set; } + [NotMapped, JsonIgnore] public Dictionary Statistics = new Dictionary(); + public string StatisticsString + { + get => JsonConvert.SerializeObject(Statistics); + set + { + if (value == null) + return; + + Statistics = JsonConvert.DeserializeObject>(value); + } + } + /// /// MD5 is kept for legacy support. /// From 2bedffc00fce72c0f15514599a6eb37ecff1b48a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 14:27:19 +0900 Subject: [PATCH 43/76] Add tests --- osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs diff --git a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs new file mode 100644 index 0000000000..274f2a6947 --- /dev/null +++ b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs @@ -0,0 +1,172 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Tests.Beatmaps.IO +{ + public class ImportScoreTest + { + public const string TEST_OSZ_PATH = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; + + [Test] + public void TestBasicImport() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestBasicImport")) + { + try + { + var osu = loadOsu(host); + + var toImport = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + Health = 0.8, + MaxCombo = 500, + Combo = 250, + User = new User { Username = "Test user" }, + Date = DateTimeOffset.Now, + OnlineScoreID = 12345, + }; + + var imported = loadIntoOsu(osu, toImport); + + Assert.AreEqual(toImport.Rank, imported.Rank); + Assert.AreEqual(toImport.TotalScore, imported.TotalScore); + Assert.AreEqual(toImport.Accuracy, imported.Accuracy); + Assert.AreEqual(toImport.Health, imported.Health); + Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo); + Assert.AreEqual(toImport.Combo, imported.Combo); + Assert.AreEqual(toImport.User.Username, imported.User.Username); + Assert.AreEqual(toImport.Date, imported.Date); + Assert.AreEqual(toImport.OnlineScoreID, imported.OnlineScoreID); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public void TestImportMods() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportMods")) + { + try + { + var osu = loadOsu(host); + + var toImport = new ScoreInfo + { + Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() }, + }; + + var imported = loadIntoOsu(osu, toImport); + + Assert.IsTrue(imported.Mods.Any(m => m is OsuModHardRock)); + Assert.IsTrue(imported.Mods.Any(m => m is OsuModDoubleTime)); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public void TestImportStatistics() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportStatistics")) + { + try + { + var osu = loadOsu(host); + + var toImport = new ScoreInfo + { + Statistics = new Dictionary + { + { HitResult.Perfect, 100 }, + { HitResult.Miss, 50 } + } + }; + + var imported = loadIntoOsu(osu, toImport); + + Assert.AreEqual(toImport.Statistics[HitResult.Perfect], imported.Statistics[HitResult.Perfect]); + Assert.AreEqual(toImport.Statistics[HitResult.Miss], imported.Statistics[HitResult.Miss]); + } + finally + { + host.Exit(); + } + } + } + + private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo scoreInfo, string guidOverride = null) + { + scoreInfo.MD5Hash = guidOverride ?? Guid.NewGuid().ToString(); + + var beatmapManager = osu.Dependencies.Get(); + + scoreInfo.BeatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + scoreInfo.Ruleset = new OsuRuleset().RulesetInfo; + + var scoreManager = osu.Dependencies.Get(); + scoreManager.Import(scoreInfo); + + var imported = scoreManager.Query(s => s.MD5Hash == scoreInfo.MD5Hash); + + return imported; + } + + private string createTemporaryBeatmap() + { + var temp = Path.GetTempFileName() + ".osz"; + File.Copy(TEST_OSZ_PATH, temp, true); + Assert.IsTrue(File.Exists(temp)); + return temp; + } + + private OsuGameBase loadOsu(GameHost host) + { + var osu = new OsuGameBase(); + Task.Run(() => host.Run(osu)); + waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); + + var beatmapFile = createTemporaryBeatmap(); + var beatmapManager = osu.Dependencies.Get(); + beatmapManager.Import(beatmapFile); + + return osu; + } + + private void waitForOrAssert(Func result, string failureMessage, int timeout = 60000) + { + Task task = Task.Run(() => + { + while (!result()) Thread.Sleep(200); + }); + + Assert.IsTrue(task.Wait(timeout), failureMessage); + } + } +} From 7543af07dd71a3a029fe5b7decb769925edc812d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:30:50 +0900 Subject: [PATCH 44/76] Remove weird reference --- osu.Game/osu.Game.csproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55132038ff..a1578b6eb8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,9 +24,4 @@ - - - ..\osu.Game.Rulesets.Osu.Tests\bin\Debug\netcoreapp2.1\osu.Game.dll - - - \ No newline at end of file + From 69370c53caef010fc7dc95eabb5f62e4a995c953 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 14:48:19 +0900 Subject: [PATCH 45/76] Fix rank not being read --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 11 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 174 +++++++++++++------ 2 files changed, 134 insertions(+), 51 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 9388d40146..755daf359a 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -20,8 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModFlashlight : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor - where T : HitObject + public abstract class ModFlashlight : Mod { public override string Name => "Flashlight"; public override string ShortenedName => "FL"; @@ -30,6 +29,14 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Restricted view area."; public override bool Ranked => true; + internal ModFlashlight() + { + } + } + + public abstract class ModFlashlight : ModFlashlight, IApplicableToRulesetContainer, IApplicableToScoreProcessor + where T : HitObject + { public const double FLASHLIGHT_FADE_DURATION = 800; protected readonly BindableInt Combo = new BindableInt(); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 5a9a09cfbc..3a57217631 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -10,6 +10,7 @@ using osu.Game.IO.Legacy; using osu.Game.Replays; using osu.Game.Replays.Legacy; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Users; @@ -47,12 +48,12 @@ namespace osu.Game.Scoring.Legacy score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; score.ScoreInfo.MD5Hash = sr.ReadString(); - var count300 = sr.ReadUInt16(); - var count100 = sr.ReadUInt16(); - var count50 = sr.ReadUInt16(); - var countGeki = sr.ReadUInt16(); - var countKatu = sr.ReadUInt16(); - var countMiss = sr.ReadUInt16(); + var count300 = (int)sr.ReadUInt16(); + var count100 = (int)sr.ReadUInt16(); + var count50 = (int)sr.ReadUInt16(); + var countGeki = (int)sr.ReadUInt16(); + var countKatu = (int)sr.ReadUInt16(); + var countMiss = (int)sr.ReadUInt16(); score.ScoreInfo.Statistics[HitResult.Great] = count300; score.ScoreInfo.Statistics[HitResult.Good] = count100; @@ -81,59 +82,134 @@ namespace osu.Game.Scoring.Legacy else if (version >= 20121008) score.ScoreInfo.OnlineScoreID = sr.ReadInt32(); - switch (score.ScoreInfo.Ruleset.ID) + if (compressedReplay?.Length > 0) { - case 0: + using (var replayInStream = new MemoryStream(compressedReplay)) { - int totalHits = count50 + count100 + count300 + countMiss; - score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; - break; - } - case 1: - { - int totalHits = count50 + count100 + count300 + countMiss; - score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; - break; - } - case 2: - { - int totalHits = count50 + count100 + count300 + countMiss + countKatu; - score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1; - break; - } - case 3: - { - int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; - score.ScoreInfo.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; - break; - } - } + byte[] properties = new byte[5]; + if (replayInStream.Read(properties, 0, 5) != 5) + throw new IOException("input .lzma is too short"); + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = replayInStream.ReadByte(); + if (v < 0) + throw new IOException("Can't Read 1"); + outSize |= (long)(byte)v << (8 * i); + } - using (var replayInStream = new MemoryStream(compressedReplay)) - { - byte[] properties = new byte[5]; - if (replayInStream.Read(properties, 0, 5) != 5) - throw new IOException("input .lzma is too short"); - long outSize = 0; - for (int i = 0; i < 8; i++) - { - int v = replayInStream.ReadByte(); - if (v < 0) - throw new IOException("Can't Read 1"); - outSize |= (long)(byte)v << (8 * i); + long compressedSize = replayInStream.Length - replayInStream.Position; + + using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) + using (var reader = new StreamReader(lzma)) + readLegacyReplay(score.Replay, reader); } - - long compressedSize = replayInStream.Length - replayInStream.Position; - - using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) - using (var reader = new StreamReader(lzma)) - readLegacyReplay(score.Replay, reader); } } + calculateAccuracy(score.ScoreInfo); + return score; } + private void calculateAccuracy(ScoreInfo score) + { + int countMiss = (int)score.Statistics[HitResult.Miss]; + int count50 = (int)score.Statistics[HitResult.Meh]; + int count100 = (int)score.Statistics[HitResult.Good]; + int count300 = (int)score.Statistics[HitResult.Great]; + int countGeki = (int)score.Statistics[HitResult.Perfect]; + int countKatu = (int)score.Statistics[HitResult.Ok]; + + switch (score.Ruleset.ID) + { + case 0: + { + int totalHits = count50 + count100 + count300 + countMiss; + score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1; + + float ratio300 = (float)count300 / totalHits; + float ratio50 = (float)count50 / totalHits; + + if (ratio300 == 1) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; + else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; + else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) + score.Rank = ScoreRank.A; + else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) + score.Rank = ScoreRank.B; + else if (ratio300 > 0.6) + score.Rank = ScoreRank.C; + else + score.Rank = ScoreRank.D; + + break; + } + case 1: + { + int totalHits = count50 + count100 + count300 + countMiss; + score.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1; + + float ratio300 = (float)count300 / totalHits; + float ratio50 = (float)count50 / totalHits; + + if (ratio300 == 1) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; + else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; + else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) + score.Rank = ScoreRank.A; + else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) + score.Rank = ScoreRank.B; + else if (ratio300 > 0.6) + score.Rank = ScoreRank.C; + else + score.Rank = ScoreRank.D; + + break; + } + case 2: + { + int totalHits = count50 + count100 + count300 + countMiss + countKatu; + score.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300) / totalHits : 1; + + if (score.Accuracy == 1) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; + else if (score.Accuracy > 0.98) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; + else if (score.Accuracy > 0.94) + score.Rank = ScoreRank.A; + else if (score.Accuracy > 0.9) + score.Rank = ScoreRank.B; + else if (score.Accuracy > 0.85) + score.Rank = ScoreRank.C; + else + score.Rank = ScoreRank.D; + break; + } + case 3: + { + int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu; + score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1; + + if (score.Accuracy == 1) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; + else if (score.Accuracy > 0.95) + score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; + else if (score.Accuracy > 0.9) + score.Rank = ScoreRank.A; + else if (score.Accuracy > 0.8) + score.Rank = ScoreRank.B; + else if (score.Accuracy > 0.7) + score.Rank = ScoreRank.C; + else + score.Rank = ScoreRank.D; + break; + } + } + } + private void readLegacyReplay(Replay replay, StreamReader reader) { float lastTime = 0; From 64bb27be5d2408569093e269b7b1e7d4ff957578 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 14:48:31 +0900 Subject: [PATCH 46/76] Add scoreinfo tables --- ...81130052804_AddScoreInfoTables.Designer.cs | 475 ++++++++++++++++++ .../20181130052804_AddScoreInfoTables.cs | 113 +++++ .../Migrations/OsuDbContextModelSnapshot.cs | 97 +++- 3 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs create mode 100644 osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs diff --git a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs new file mode 100644 index 0000000000..273c4fbdaa --- /dev/null +++ b/osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs @@ -0,0 +1,475 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20181130052804_AddScoreInfoTables")] + partial class AddScoreInfoTables + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Health"); + + b.Property("MD5Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsString"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsString"); + + b.Property("TotalScore"); + + b.Property("UserString"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "BeatmapInfo") + .WithMany() + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs b/osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs new file mode 100644 index 0000000000..470f541c32 --- /dev/null +++ b/osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs @@ -0,0 +1,113 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddScoreInfoTables : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ScoreInfo", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Rank = table.Column(nullable: false), + TotalScore = table.Column(nullable: false), + Accuracy = table.Column(nullable: false), + Health = table.Column(nullable: false), + PP = table.Column(nullable: true), + MaxCombo = table.Column(nullable: false), + Combo = table.Column(nullable: false), + RulesetID = table.Column(nullable: false), + ModsString = table.Column(nullable: true), + UserString = table.Column(nullable: true), + BeatmapInfoID = table.Column(nullable: false), + OnlineScoreID = table.Column(nullable: true), + Date = table.Column(nullable: false), + StatisticsString = table.Column(nullable: true), + MD5Hash = table.Column(nullable: true), + DeletePending = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ScoreInfo", x => x.ID); + table.ForeignKey( + name: "FK_ScoreInfo_BeatmapInfo_BeatmapInfoID", + column: x => x.BeatmapInfoID, + principalTable: "BeatmapInfo", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ScoreInfo_RulesetInfo_RulesetID", + column: x => x.RulesetID, + principalTable: "RulesetInfo", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ScoreFileInfo", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + FileInfoID = table.Column(nullable: false), + Filename = table.Column(nullable: false), + ScoreInfoID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ScoreFileInfo", x => x.ID); + table.ForeignKey( + name: "FK_ScoreFileInfo_FileInfo_FileInfoID", + column: x => x.FileInfoID, + principalTable: "FileInfo", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ScoreFileInfo_ScoreInfo_ScoreInfoID", + column: x => x.ScoreInfoID, + principalTable: "ScoreInfo", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_ScoreFileInfo_FileInfoID", + table: "ScoreFileInfo", + column: "FileInfoID"); + + migrationBuilder.CreateIndex( + name: "IX_ScoreFileInfo_ScoreInfoID", + table: "ScoreFileInfo", + column: "ScoreInfoID"); + + migrationBuilder.CreateIndex( + name: "IX_ScoreInfo_BeatmapInfoID", + table: "ScoreInfo", + column: "BeatmapInfoID"); + + migrationBuilder.CreateIndex( + name: "IX_ScoreInfo_OnlineScoreID", + table: "ScoreInfo", + column: "OnlineScoreID", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ScoreInfo_RulesetID", + table: "ScoreInfo", + column: "RulesetID"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ScoreFileInfo"); + + migrationBuilder.DropTable( + name: "ScoreInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 663676a6d3..c44fdcf8dd 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -281,6 +281,76 @@ namespace osu.Game.Migrations b.ToTable("RulesetInfo"); }); + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Health"); + + b.Property("MD5Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsString"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsString"); + + b.Property("TotalScore"); + + b.Property("UserString"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => { b.Property("ID") @@ -360,6 +430,31 @@ namespace osu.Game.Migrations .HasForeignKey("MetadataID"); }); + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "BeatmapInfo") + .WithMany() + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => { b.HasOne("osu.Game.IO.FileInfo", "FileInfo") From 0ee5a5bdb4404850493c06d520c904ecb8bf9ca3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:57:25 +0900 Subject: [PATCH 47/76] Add support for keyboard seeking in the editor --- osu.Game/Screens/Edit/Editor.cs | 66 +++++++++++++++++++--------- osu.Game/Screens/Edit/EditorClock.cs | 12 +++-- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c4fb9dc419..6d81897552 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -20,6 +20,7 @@ using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Design; +using osuTK.Input; namespace osu.Game.Screens.Edit { @@ -157,29 +158,19 @@ namespace osu.Game.Screens.Edit bottomBackground.Colour = colours.Gray2; } - private void exportBeatmap() + protected override bool OnKeyDown(KeyDownEvent e) { - host.OpenFileExternally(Beatmap.Value.Save()); - } - - private void onModeChanged(EditorScreenMode mode) - { - currentScreen?.Exit(); - - switch (mode) + switch (e.Key) { - case EditorScreenMode.Compose: - currentScreen = new ComposeScreen(); - break; - case EditorScreenMode.Design: - currentScreen = new DesignScreen(); - break; - default: - currentScreen = new EditorScreen(); - break; + case Key.Left: + seek(-1); + return true; + case Key.Right: + seek(1); + return true; } - LoadComponentAsync(currentScreen, screenContainer.Add); + return base.OnKeyDown(e); } private double scrollAccumulation; @@ -193,9 +184,9 @@ namespace osu.Game.Screens.Edit while (Math.Abs(scrollAccumulation) > precision) { if (scrollAccumulation > 0) - clock.SeekBackward(!clock.IsRunning); + seek(-1); else - clock.SeekForward(!clock.IsRunning); + seek(1); scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); } @@ -224,7 +215,40 @@ namespace osu.Game.Screens.Edit Beatmap.Value.Track.Tempo.Value = 1; Beatmap.Value.Track.Start(); } + return base.OnExiting(next); } + + private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); + + private void onModeChanged(EditorScreenMode mode) + { + currentScreen?.Exit(); + + switch (mode) + { + case EditorScreenMode.Compose: + currentScreen = new ComposeScreen(); + break; + case EditorScreenMode.Design: + currentScreen = new DesignScreen(); + break; + default: + currentScreen = new EditorScreen(); + break; + } + + LoadComponentAsync(currentScreen, screenContainer.Add); + } + + private void seek(int direction) + { + double amount = GetContainingInputManager().CurrentState.Keyboard.ShiftPressed ? 2 : 1; + + if (direction < 1) + clock.SeekBackward(!clock.IsRunning, amount); + else + clock.SeekForward(!clock.IsRunning, amount); + } } } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 465e3a43e2..aa30b1a9f5 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -68,16 +68,20 @@ namespace osu.Game.Screens.Edit /// Seeks backwards by one beat length. /// /// Whether to snap to the closest beat after seeking. - public void SeekBackward(bool snapped = false) => seek(-1, snapped); + /// The relative amount (magnitude) which should be seeked. + public void SeekBackward(bool snapped = false, double amount = 1) => seek(-1, snapped, amount); /// /// Seeks forwards by one beat length. /// /// Whether to snap to the closest beat after seeking. - public void SeekForward(bool snapped = false) => seek(1, snapped); + /// The relative amount (magnitude) which should be seeked. + public void SeekForward(bool snapped = false, double amount = 1) => seek(1, snapped, amount); - private void seek(int direction, bool snapped) + private void seek(int direction, bool snapped, double amount = 1) { + if (amount <= 0) throw new ArgumentException("Value should be greater than zero", nameof(amount)); + var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime); if (direction < 0 && timingPoint.Time == CurrentTime) { @@ -87,7 +91,7 @@ namespace osu.Game.Screens.Edit timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; } - double seekAmount = timingPoint.BeatLength / beatDivisor; + double seekAmount = timingPoint.BeatLength / beatDivisor * amount; double seekTime = CurrentTime + seekAmount * direction; if (!snapped || ControlPointInfo.TimingPoints.Count == 0) From ab621bd87348738f416b5f162134d2c717d693b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:41:17 +0900 Subject: [PATCH 48/76] Toggle pause in editor with spacebar --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 7d68f32495..d2e51d1f57 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -13,6 +13,7 @@ using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Screens.Edit.Components { @@ -63,6 +64,18 @@ namespace osu.Game.Screens.Edit.Components tabs.Current.ValueChanged += newValue => Beatmap.Value.Track.Tempo.Value = newValue; } + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Space: + togglePause(); + return true; + } + + return base.OnKeyDown(e); + } + private void togglePause() { if (adjustableClock.IsRunning) From 705ef5e3acc314d86cf5bfacd9237b65148654c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 15:09:15 +0900 Subject: [PATCH 49/76] Fix hash function --- osu.Game/Database/ArchiveModelManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index e2157f5fb3..203c157550 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -207,7 +207,7 @@ namespace osu.Game.Database if (model == null) return null; - model.Hash = computeBeatmapSetHash(archive); + model.Hash = computeHash(archive); return Import(model, archive); } @@ -226,13 +226,13 @@ namespace osu.Game.Database protected abstract string[] HashableFileTypes { get; } /// - /// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content. + /// Create a SHA-2 hash from the provided archive based on file content of all files matching . /// - private string computeBeatmapSetHash(ArchiveReader reader) + private string computeHash(ArchiveReader reader) { // for now, concatenate all .osu files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); - foreach (string file in reader.Filenames.Where(f => f.EndsWith(".osu"))) + foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith))) using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); From 831cd3ed596bb96a40cf09223cabf152d671e9ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 15:18:52 +0900 Subject: [PATCH 50/76] ScoreInfo scoreInfo -> ScoreInfo score --- .../Difficulty/ManiaPerformanceCalculator.cs | 20 +++++++------- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Difficulty/OsuPerformanceCalculator.cs | 18 ++++++------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 12 ++++----- .../Difficulty/TaikoPerformanceCalculator.cs | 20 +++++++------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs | 12 ++++----- osu.Game/OsuGame.cs | 14 +++++----- .../BeatmapSet/Scores/DrawableScore.cs | 16 ++++++------ .../BeatmapSet/Scores/DrawableTopScore.cs | 26 +++++++++---------- .../BeatmapSet/Scores/ScoresContainer.cs | 2 +- .../Ranks/DrawablePerformanceScore.cs | 6 ++--- .../Sections/Ranks/DrawableProfileScore.cs | 16 ++++++------ .../Sections/Ranks/DrawableTotalScore.cs | 6 ++--- .../Difficulty/PerformanceCalculator.cs | 12 ++++----- osu.Game/Rulesets/Ruleset.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 16 ++++++------ osu.Game/Scoring/LegacyDatabasedScore.cs | 6 ++--- osu.Game/Scoring/ScoreManager.cs | 2 +- osu.Game/Screens/Ranking/Results.cs | 14 +++++----- osu.Game/Screens/Ranking/ResultsPage.cs | 6 ++--- .../Screens/Ranking/ResultsPageRanking.cs | 4 +-- osu.Game/Screens/Ranking/ResultsPageScore.cs | 12 ++++----- .../Select/Leaderboards/LeaderboardScore.cs | 22 ++++++++-------- 25 files changed, 135 insertions(+), 135 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index a845f1d2ad..610c7a8fee 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -28,21 +28,21 @@ namespace osu.Game.Rulesets.Mania.Difficulty private int countMeh; private int countMiss; - public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) - : base(ruleset, beatmap, scoreInfo) + public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score) + : base(ruleset, beatmap, score) { } public override double Calculate(Dictionary categoryDifficulty = null) { - mods = ScoreInfo.Mods; - scaledScore = ScoreInfo.TotalScore; - countPerfect = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Perfect]); - countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); - countOk = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Ok]); - countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); + mods = Score.Mods; + scaledScore = Score.TotalScore; + countPerfect = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countOk = Convert.ToInt32(Score.Statistics[HitResult.Ok]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); if (mods.Any(m => !m.Ranked)) return 0; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index e02e6225e3..392d10b414 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new ManiaPerformanceCalculator(this, beatmap, scoreInfo); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index ed6bdbd155..5e66d43c98 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty private int countMeh; private int countMiss; - public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) - : base(ruleset, beatmap, scoreInfo) + public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score) + : base(ruleset, beatmap, score) { countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); @@ -42,13 +42,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty public override double Calculate(Dictionary categoryRatings = null) { - mods = ScoreInfo.Mods; - accuracy = ScoreInfo.Accuracy; - scoreMaxCombo = ScoreInfo.MaxCombo; - countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); + mods = Score.Mods; + accuracy = Score.Accuracy; + scoreMaxCombo = Score.MaxCombo; + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index dac9181fc9..d1192e4165 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new OsuPerformanceCalculator(this, beatmap, scoreInfo); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new OsuPerformanceCalculator(this, beatmap, score); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index cec6c50677..9b3da1b8a8 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -40,14 +40,14 @@ namespace osu.Game.Rulesets.Osu.Scoring comboResultCounts.Clear(); } - public override void PopulateScore(ScoreInfo scoreInfo) + public override void PopulateScore(ScoreInfo score) { - base.PopulateScore(scoreInfo); + base.PopulateScore(score); - scoreInfo.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); - scoreInfo.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); - scoreInfo.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); - scoreInfo.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); + score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); + score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); + score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); + score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); } private const double harshness = 0.01; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 788c09d75a..e4960c9680 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -23,18 +23,18 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private int countMeh; private int countMiss; - public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) - : base(ruleset, beatmap, scoreInfo) + public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score) + : base(ruleset, beatmap, score) { } public override double Calculate(Dictionary categoryDifficulty = null) { - mods = ScoreInfo.Mods; - countGreat = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(ScoreInfo.Statistics[HitResult.Miss]); + mods = Score.Mods; + countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); + countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); + countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); + countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty // Combo scaling if (Attributes.MaxCombo > 0) - strainValue *= Math.Min(Math.Pow(ScoreInfo.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); + strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); if (mods.Any(m => m is ModHidden)) strainValue *= 1.025; @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty strainValue *= 1.05 * lengthBonus; // Scale the speed value with accuracy _slightly_ - return strainValue * ScoreInfo.Accuracy; + return strainValue * Score.Accuracy; } private double computeAccuracyValue() @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(ScoreInfo.Accuracy, 15) * 22.0; + double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 9b425c0ce9..7094f9d71b 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => new TaikoPerformanceCalculator(this, beatmap, scoreInfo); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new TaikoPerformanceCalculator(this, beatmap, score); public override int? LegacyID => 1; diff --git a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs index 274f2a6947..3e7a4424df 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs @@ -121,19 +121,19 @@ namespace osu.Game.Tests.Beatmaps.IO } } - private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo scoreInfo, string guidOverride = null) + private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score, string guidOverride = null) { - scoreInfo.MD5Hash = guidOverride ?? Guid.NewGuid().ToString(); + score.MD5Hash = guidOverride ?? Guid.NewGuid().ToString(); var beatmapManager = osu.Dependencies.Get(); - scoreInfo.BeatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); - scoreInfo.Ruleset = new OsuRuleset().RulesetInfo; + score.BeatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); - scoreManager.Import(scoreInfo); + scoreManager.Import(score); - var imported = scoreManager.Query(s => s.MD5Hash == scoreInfo.MD5Hash); + var imported = scoreManager.Query(s => s.MD5Hash == score.MD5Hash); return imported; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 830cefc58c..7d66bf9cfb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -248,7 +248,7 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); - protected void LoadScore(ScoreInfo scoreInfo) + protected void LoadScore(ScoreInfo score) { scoreLoad?.Cancel(); @@ -256,18 +256,18 @@ namespace osu.Game if (menu == null) { - scoreLoad = Schedule(() => LoadScore(scoreInfo)); + scoreLoad = Schedule(() => LoadScore(score)); return; } if (!menu.IsCurrentScreen) { menu.MakeCurrent(); - this.Delay(500).Schedule(() => LoadScore(scoreInfo), out scoreLoad); + this.Delay(500).Schedule(() => LoadScore(score), out scoreLoad); return; } - var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfo.ID); if (databasedBeatmap == null) { @@ -279,12 +279,12 @@ namespace osu.Game return; } - ruleset.Value = scoreInfo.Ruleset; + ruleset.Value = score.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Beatmap.Value.Mods.Value = scoreInfo.Mods; + Beatmap.Value.Mods.Value = score.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(scoreInfo).Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(score).Replay))); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 1b079f33ea..f643e130aa 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; - public DrawableScore(int index, APIScoreInfo scoreInfo) + public DrawableScore(int index, APIScoreInfo score) { ScoreModsContainer modsContainer; @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Font = @"Exo2.0-RegularItalic", Margin = new MarginPadding { Left = side_margin } }, - new DrawableFlag(scoreInfo.User.Country) + new DrawableFlag(score.User.Country) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - User = scoreInfo.User, + User = score.User, Margin = new MarginPadding { Left = 100 } }, modsContainer = new ScoreModsContainer @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativePositionAxes = Axes.X, X = 0.42f }, - new DrawableRank(scoreInfo.Rank) + new DrawableRank(score.Rank) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, - Text = $@"{scoreInfo.TotalScore:N0}", + Text = $@"{score.TotalScore:N0}", Font = @"Venera", RelativePositionAxes = Axes.X, X = 0.75f, @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, - Text = $@"{scoreInfo.Accuracy:P2}", + Text = $@"{score.Accuracy:P2}", Font = @"Exo2.0-RegularItalic", RelativePositionAxes = Axes.X, X = 0.85f @@ -105,13 +105,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Text = $"{scoreInfo.Statistics[HitResult.Great]}/{scoreInfo.Statistics[HitResult.Good]}/{scoreInfo.Statistics[HitResult.Meh]}", + Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}", Font = @"Exo2.0-RegularItalic", Margin = new MarginPadding { Right = side_margin } }, }; - foreach (Mod mod in scoreInfo.Mods) + foreach (Mod mod in score.Mods) modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index b5e008d5da..643839fa88 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -43,26 +43,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly InfoColumn statistics; private readonly ScoreModsContainer modsContainer; - private APIScoreInfo scoreInfo; - public APIScoreInfo ScoreInfo + private APIScoreInfo score; + public APIScoreInfo Score { - get { return scoreInfo; } + get { return score; } set { - if (scoreInfo == value) return; - scoreInfo = value; + if (score == value) return; + score = value; - avatar.User = username.User = scoreInfo.User; - flag.Country = scoreInfo.User.Country; - date.Text = $@"achieved {scoreInfo.Date:MMM d, yyyy}"; - rank.UpdateRank(scoreInfo.Rank); + avatar.User = username.User = score.User; + flag.Country = score.User.Country; + date.Text = $@"achieved {score.Date:MMM d, yyyy}"; + rank.UpdateRank(score.Rank); - totalScore.Value = $@"{scoreInfo.TotalScore:N0}"; - accuracy.Value = $@"{scoreInfo.Accuracy:P2}"; - statistics.Value = $"{scoreInfo.Statistics[HitResult.Great]}/{scoreInfo.Statistics[HitResult.Good]}/{scoreInfo.Statistics[HitResult.Meh]}"; + totalScore.Value = $@"{score.TotalScore:N0}"; + accuracy.Value = $@"{score.Accuracy:P2}"; + statistics.Value = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}"; modsContainer.Clear(); - foreach (Mod mod in scoreInfo.Mods) + foreach (Mod mod in score.Mods) modsContainer.Add(new ModIcon(mod) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index f2ffea9ae6..e338d2f90f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } - topScore.ScoreInfo = scores.FirstOrDefault(); + topScore.Score = scores.FirstOrDefault(); topScore.Show(); flow.Clear(); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index a4f05b0f96..98a4bdba45 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -13,8 +13,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly double? weight; - public DrawablePerformanceScore(ScoreInfo scoreInfo, double? weight = null) - : base(scoreInfo) + public DrawablePerformanceScore(ScoreInfo score, double? weight = null) + : base(score) { this.weight = weight; } @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks [BackgroundDependencyLoader] private void load(OsuColour colour) { - double pp = ScoreInfo.PP ?? 0; + double pp = Score.PP ?? 0; RightFlowContainer.Add(new OsuSpriteText { Text = $"{pp:0}pp", diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index a74d6ca35e..c3180a1abe 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -16,11 +16,11 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks public abstract class DrawableProfileScore : DrawableProfileRow { private readonly ScoreModsContainer modsContainer; - protected readonly ScoreInfo ScoreInfo; + protected readonly ScoreInfo Score; - protected DrawableProfileScore(ScoreInfo scoreInfo) + protected DrawableProfileScore(ScoreInfo score) { - ScoreInfo = scoreInfo; + Score = score; RelativeSizeAxes = Axes.X; Height = 60; @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { var text = new OsuSpriteText { - Text = $"accuracy: {ScoreInfo.Accuracy:P2}", + Text = $"accuracy: {Score.Accuracy:P2}", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, @@ -53,14 +53,14 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RightFlowContainer.Add(text); RightFlowContainer.SetLayoutPosition(text, 1); - LeftFlowContainer.Add(new BeatmapMetadataContainer(ScoreInfo.BeatmapInfo)); - LeftFlowContainer.Add(new DrawableDate(ScoreInfo.Date)); + LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.BeatmapInfo)); + LeftFlowContainer.Add(new DrawableDate(Score.Date)); - foreach (Mod mod in ScoreInfo.Mods) + foreach (Mod mod in Score.Mods) modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) }); } - protected override Drawable CreateLeftVisual() => new DrawableRank(ScoreInfo.Rank) + protected override Drawable CreateLeftVisual() => new DrawableRank(Score.Rank) { RelativeSizeAxes = Axes.Y, Width = 60, diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index 268ba57b75..a48468e4e5 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -10,8 +10,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { public class DrawableTotalScore : DrawableProfileScore { - public DrawableTotalScore(ScoreInfo scoreInfo) - : base(scoreInfo) + public DrawableTotalScore(ScoreInfo score) + : base(score) { } @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { RightFlowContainer.Add(new OsuSpriteText { - Text = ScoreInfo.TotalScore.ToString("#,###"), + Text = Score.TotalScore.ToString("#,###"), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, TextSize = 18, diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 8b1a54fc7c..48a68928de 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -17,21 +17,21 @@ namespace osu.Game.Rulesets.Difficulty protected readonly Ruleset Ruleset; protected readonly IBeatmap Beatmap; - protected readonly ScoreInfo ScoreInfo; + protected readonly ScoreInfo Score; protected double TimeRate { get; private set; } = 1; - protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo scoreInfo) + protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score) { Ruleset = ruleset; - ScoreInfo = scoreInfo; + Score = score; - beatmap.Mods.Value = scoreInfo.Mods; + beatmap.Mods.Value = score.Mods; Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); - Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(scoreInfo.Mods); + Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods); - ApplyMods(scoreInfo.Mods); + ApplyMods(score.Mods); } protected virtual void ApplyMods(Mod[] mods) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 86bd6d9072..53e3e40374 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets public abstract DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap); - public virtual PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo scoreInfo) => null; + public virtual PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => null; public virtual HitObjectComposer CreateHitObjectComposer() => null; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 632ebcec6b..830f13ad6d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -158,15 +158,15 @@ namespace osu.Game.Rulesets.Scoring /// /// Retrieve a score populated with data for the current play this processor is responsible for. /// - public virtual void PopulateScore(ScoreInfo scoreInfo) + public virtual void PopulateScore(ScoreInfo score) { - scoreInfo.TotalScore = TotalScore; - scoreInfo.Combo = Combo; - scoreInfo.MaxCombo = HighestCombo; - scoreInfo.Accuracy = Accuracy; - scoreInfo.Rank = Rank; - scoreInfo.Date = DateTimeOffset.Now; - scoreInfo.Health = Health; + score.TotalScore = TotalScore; + score.Combo = Combo; + score.MaxCombo = HighestCombo; + score.Accuracy = Accuracy; + score.Rank = Rank; + score.Date = DateTimeOffset.Now; + score.Health = Health; } } diff --git a/osu.Game/Scoring/LegacyDatabasedScore.cs b/osu.Game/Scoring/LegacyDatabasedScore.cs index 29996d5c01..768c5da7af 100644 --- a/osu.Game/Scoring/LegacyDatabasedScore.cs +++ b/osu.Game/Scoring/LegacyDatabasedScore.cs @@ -12,11 +12,11 @@ namespace osu.Game.Scoring { public class LegacyDatabasedScore : Score { - public LegacyDatabasedScore(ScoreInfo scoreInfo, RulesetStore rulesets, BeatmapManager beatmaps, IResourceStore store) + public LegacyDatabasedScore(ScoreInfo score, RulesetStore rulesets, BeatmapManager beatmaps, IResourceStore store) { - ScoreInfo = scoreInfo; + ScoreInfo = score; - var replayFilename = scoreInfo.Files.First(f => f.Filename.EndsWith(".osr", StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; + var replayFilename = score.Files.First(f => f.Filename.EndsWith(".osr", StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; using (var stream = store.GetStream(replayFilename)) Replay = new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).Replay; diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 5eedf3bcf8..5d16d40346 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring return null; } - public Score GetScore(ScoreInfo scoreInfo) => new LegacyDatabasedScore(scoreInfo, rulesets, beatmaps, Files.Store); + public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps, Files.Store); public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 89674c1ed0..1ff5fc7bfd 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Ranking { public class Results : OsuScreen { - private readonly ScoreInfo scoreInfo; + private readonly ScoreInfo score; private Container circleOuterBackground; private Container circleOuter; private Container circleInner; @@ -44,9 +44,9 @@ namespace osu.Game.Screens.Ranking private const float circle_outer_scale = 0.96f; - public Results(ScoreInfo scoreInfo) + public Results(ScoreInfo score) { - this.scoreInfo = scoreInfo; + this.score = score; } private const float transition_time = 800; @@ -188,7 +188,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{scoreInfo.MaxCombo}x", + Text = $"{score.MaxCombo}x", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -209,7 +209,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{scoreInfo.Accuracy:P2}", + Text = $"{score.Accuracy:P2}", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -274,10 +274,10 @@ namespace osu.Game.Screens.Ranking switch (mode) { case ResultMode.Summary: - currentPage = new ResultsPageScore(scoreInfo, Beatmap.Value); + currentPage = new ResultsPageScore(score, Beatmap.Value); break; case ResultMode.Ranking: - currentPage = new ResultsPageRanking(scoreInfo, Beatmap.Value); + currentPage = new ResultsPageRanking(score, Beatmap.Value); break; } diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index eb09ceb574..5f68623e54 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -16,16 +16,16 @@ namespace osu.Game.Screens.Ranking { public class ResultsPage : Container { - protected readonly ScoreInfo ScoreInfo; + protected readonly ScoreInfo Score; protected readonly WorkingBeatmap Beatmap; private CircularContainer content; private Box fill; protected override Container Content => content; - public ResultsPage(ScoreInfo scoreInfo, WorkingBeatmap beatmap) + public ResultsPage(ScoreInfo score, WorkingBeatmap beatmap) { - ScoreInfo = scoreInfo; + Score = score; Beatmap = beatmap; RelativeSizeAxes = Axes.Both; } diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index 235aa632cd..6db34fc071 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Ranking { public class ResultsPageRanking : ResultsPage { - public ResultsPageRanking(ScoreInfo scoreInfo, WorkingBeatmap beatmap = null) : base(scoreInfo, beatmap) + public ResultsPageRanking(ScoreInfo score, WorkingBeatmap beatmap = null) : base(score, beatmap) { } @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.Centre, Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Beatmap = Beatmap.BeatmapInfo ?? ScoreInfo.BeatmapInfo, + Beatmap = Beatmap.BeatmapInfo ?? Score.BeatmapInfo, Scale = new Vector2(0.7f) } }; diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 6641ccaf8c..153d154d40 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking private Container scoreContainer; private ScoreCounter scoreCounter; - public ResultsPageScore(ScoreInfo scoreInfo, WorkingBeatmap beatmap) : base(scoreInfo, beatmap) { } + public ResultsPageScore(ScoreInfo score, WorkingBeatmap beatmap) : base(score, beatmap) { } private FillFlowContainer statisticsContainer; @@ -64,14 +64,14 @@ namespace osu.Game.Screens.Ranking Direction = FillDirection.Vertical, Children = new Drawable[] { - new UserHeader(ScoreInfo.User) + new UserHeader(Score.User) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = user_header_height, }, - new DrawableRank(ScoreInfo.Rank) + new DrawableRank(Score.Rank) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.TopCentre, Margin = new MarginPadding { Bottom = 10 }, }, - new DateTimeDisplay(ScoreInfo.Date.LocalDateTime) + new DateTimeDisplay(Score.Date.LocalDateTime) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -166,7 +166,7 @@ namespace osu.Game.Screens.Ranking } }; - statisticsContainer.ChildrenEnumerable = ScoreInfo.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s)); + statisticsContainer.ChildrenEnumerable = Score.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s)); } protected override void LoadComplete() @@ -175,7 +175,7 @@ namespace osu.Game.Screens.Ranking Schedule(() => { - scoreCounter.Increment(ScoreInfo.TotalScore); + scoreCounter.Increment(Score.TotalScore); int delay = 0; foreach (var s in statisticsContainer.Children) diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 4356deeb94..1ba529c0bf 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Select.Leaderboards public static readonly float HEIGHT = 60; public readonly int RankPosition; - public readonly ScoreInfo ScoreInfo; + public readonly ScoreInfo Score; private const float corner_radius = 5; private const float edge_margin = 5; @@ -43,9 +43,9 @@ namespace osu.Game.Screens.Select.Leaderboards private Container flagBadgeContainer; private FillFlowContainer modsContainer; - public LeaderboardScore(ScoreInfo scoreInfo, int rank) + public LeaderboardScore(ScoreInfo score, int rank) { - ScoreInfo = scoreInfo; + Score = score; RankPosition = rank; RelativeSizeAxes = Axes.X; @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new[] { avatar = new DelayedLoadWrapper( - new Avatar(ScoreInfo.User) + new Avatar(Score.User) { RelativeSizeAxes = Axes.Both, CornerRadius = corner_radius, @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Select.Leaderboards { nameLabel = new OsuSpriteText { - Text = ScoreInfo.User.Username, + Text = Score.User.Username, Font = @"Exo2.0-BoldItalic", TextSize = 23, }, @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Select.Leaderboards Masking = true, Children = new Drawable[] { - new DrawableFlag(ScoreInfo.User?.Country) + new DrawableFlag(Score.User?.Country) { Width = 30, RelativeSizeAxes = Axes.Y, @@ -166,8 +166,8 @@ namespace osu.Game.Screens.Select.Leaderboards Margin = new MarginPadding { Left = edge_margin }, Children = new Drawable[] { - maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, ScoreInfo.MaxCombo.ToString(), "Max Combo"), - accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(ScoreInfo.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", ScoreInfo.Accuracy), "Accuracy"), + maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, Score.MaxCombo.ToString(), "Max Combo"), + accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(Score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", Score.Accuracy), "Accuracy"), }, }, }, @@ -183,13 +183,13 @@ namespace osu.Game.Screens.Select.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(ScoreInfo.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText(Score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), new Container { Size = new Vector2(40f, 20f), Children = new[] { - scoreRank = new DrawableRank(ScoreInfo.Rank) + scoreRank = new DrawableRank(Score.Rank) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -205,7 +205,7 @@ namespace osu.Game.Screens.Select.Leaderboards Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = ScoreInfo.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) + ChildrenEnumerable = Score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, }, From bc3fcb87b752aab58263a65d4c08b7930c070035 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 15:47:55 +0900 Subject: [PATCH 51/76] Use input events rather than scene graph traversals --- osu.Game/Screens/Edit/Editor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 6d81897552..9bccefc508 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -163,10 +163,10 @@ namespace osu.Game.Screens.Edit switch (e.Key) { case Key.Left: - seek(-1); + seek(e, -1); return true; case Key.Right: - seek(1); + seek(e, 1); return true; } @@ -184,9 +184,9 @@ namespace osu.Game.Screens.Edit while (Math.Abs(scrollAccumulation) > precision) { if (scrollAccumulation > 0) - seek(-1); + seek(e, -1); else - seek(1); + seek(e, 1); scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); } @@ -241,9 +241,9 @@ namespace osu.Game.Screens.Edit LoadComponentAsync(currentScreen, screenContainer.Add); } - private void seek(int direction) + private void seek(UIEvent e, int direction) { - double amount = GetContainingInputManager().CurrentState.Keyboard.ShiftPressed ? 2 : 1; + double amount = e.ShiftPressed ? 2 : 1; if (direction < 1) clock.SeekBackward(!clock.IsRunning, amount); From 37279559119a5b69e59773d6957db68f50f051fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 16:11:09 +0900 Subject: [PATCH 52/76] Refactors/renames --- osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs | 2 +- .../Online/API/Requests/GetScoresRequest.cs | 2 +- .../API/Requests/Responses/APIScoreInfo.cs | 34 +++++++----- osu.Game/OsuGame.cs | 2 +- .../Sections/Ranks/DrawableProfileScore.cs | 2 +- .../Sections/Ranks/PaginatedScoreContainer.cs | 5 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 2 +- osu.Game/Scoring/ScoreInfo.cs | 55 +++++++++++++++---- osu.Game/Scoring/ScoreStore.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- .../Screens/Ranking/ResultsPageRanking.cs | 2 +- 11 files changed, 77 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs index 3e7a4424df..76ebbef784 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Beatmaps.IO var beatmapManager = osu.Dependencies.Get(); - score.BeatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + score.Beatmap = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); score.Ruleset = new OsuRuleset().RulesetInfo; var scoreManager = osu.Dependencies.Get(); diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 99207dccc6..2751dd956b 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -34,7 +34,7 @@ namespace osu.Game.Online.API.Requests private void onSuccess(APIScores r) { foreach (APIScoreInfo score in r.Scores) - score.ApplyBeatmap(beatmap); + score.Beatmap = beatmap; } protected override WebRequest CreateWebRequest() diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 19f8206667..13633ce1e1 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -33,9 +33,6 @@ namespace osu.Game.Online.API.Requests.Responses set => User = value; } - [JsonProperty(@"mode_int")] - public int OnlineRulesetID { get; set; } - [JsonProperty(@"score_id")] private long onlineScoreID { @@ -51,7 +48,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"beatmap")] private BeatmapInfo beatmap { - set => BeatmapInfo = value; + set => Beatmap = value; } [JsonProperty(@"beatmapset")] @@ -60,10 +57,10 @@ namespace osu.Game.Online.API.Requests.Responses set { // extract the set ID to its correct place. - BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID }; + Beatmap.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID }; value.ID = 0; - BeatmapInfo.Metadata = value; + Beatmap.Metadata = value; } } @@ -98,21 +95,32 @@ namespace osu.Game.Online.API.Requests.Responses } } + [JsonProperty(@"mode_int")] + public int OnlineRulesetID { get; set; } + [JsonProperty(@"mods")] private string[] modStrings { get; set; } - public void ApplyBeatmap(BeatmapInfo beatmap) + public override BeatmapInfo Beatmap { - BeatmapInfo = beatmap; - ApplyRuleset(beatmap.Ruleset); + get => base.Beatmap; + set + { + base.Beatmap = value; + Ruleset = value.Ruleset; + } } - public void ApplyRuleset(RulesetInfo ruleset) + public override RulesetInfo Ruleset { - Ruleset = ruleset; + get => base.Ruleset; + set + { + base.Ruleset = value; - // Evaluate the mod string - Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray(); + // Evaluate the mod string + Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray(); + } } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7d66bf9cfb..eeeb24d7d4 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -267,7 +267,7 @@ namespace osu.Game return; } - var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == score.BeatmapInfo.ID); + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == score.Beatmap.ID); if (databasedBeatmap == null) { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index c3180a1abe..1c39cb309c 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -53,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks RightFlowContainer.Add(text); RightFlowContainer.SetLayoutPosition(text, 1); - LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.BeatmapInfo)); + LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap)); LeftFlowContainer.Add(new DrawableDate(Score.Date)); foreach (Mod mod in Score.Mods) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 3c0c810fce..441cb2c29f 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -9,6 +9,7 @@ using osu.Game.Users; using System; using System.Linq; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks { @@ -29,6 +30,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Direction = FillDirection.Vertical; } + private ScoreManager scoreManager; + protected override void ShowMore() { base.ShowMore(); @@ -37,7 +40,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks request.Success += scores => Schedule(() => { foreach (var s in scores) - s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID)); + s.Ruleset = Rulesets.GetRuleset(s.RulesetID); ShowMoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 3a57217631..edc8ed65d8 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -43,7 +43,7 @@ namespace osu.Game.Scoring.Legacy throw new BeatmapNotFoundException(); currentBeatmap = workingBeatmap.Beatmap; - score.ScoreInfo.BeatmapInfo = currentBeatmap.BeatmapInfo; + score.ScoreInfo.Beatmap = currentBeatmap.BeatmapInfo; score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; score.ScoreInfo.MD5Hash = sr.ReadString(); diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 6f06f2400b..62d9ca7c2c 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -36,27 +36,49 @@ namespace osu.Game.Scoring public int RulesetID { get; set; } - public RulesetInfo Ruleset { get; set; } + public virtual RulesetInfo Ruleset { get; set; } - [NotMapped, JsonIgnore] + private Mod[] mods; + + [NotMapped] public Mod[] Mods { get { - if (ModsString == null) + if (mods != null) return mods; + + if (modsJson == null) return Array.Empty(); - var deserialized = JsonConvert.DeserializeObject(ModsString); - return Ruleset.CreateInstance().GetAllMods().Where(mod => deserialized.Any(d => d == mod.ShortenedName)).ToArray(); + return getModsFromRuleset(JsonConvert.DeserializeObject(modsJson)); + } + set + { + mods = value; + ModsJson = null; } - set => ModsString = JsonConvert.SerializeObject(value.Select(m => m.ShortenedName).ToArray()); } - public string ModsString { get; set; } + private Mod[] getModsFromRuleset(DeserializedMod[] mods) => Ruleset.CreateInstance().GetAllMods().Where(mod => mods.Any(d => d.ShortenedName == mod.ShortenedName)).ToArray(); + + private string modsJson; + + [Column("Mods")] + public string ModsJson + { + get => modsJson ?? JsonConvert.SerializeObject(Mods); + set + { + modsJson = value; + + // we potentially can't update this yet due to Ruleset being late-bound, so instead update on read as necessary. + mods = null; + } + } - [NotMapped, JsonIgnore] public User User; + [Column("User")] public string UserString { get => User?.Username; @@ -65,22 +87,25 @@ namespace osu.Game.Scoring public int BeatmapInfoID { get; set; } - public BeatmapInfo BeatmapInfo { get; set; } + public virtual BeatmapInfo Beatmap { get; set; } public long? OnlineScoreID { get; set; } public DateTimeOffset Date { get; set; } - [NotMapped, JsonIgnore] public Dictionary Statistics = new Dictionary(); - public string StatisticsString + [Column("Statistics")] + public string StatisticsJson { get => JsonConvert.SerializeObject(Statistics); set { if (value == null) + { + Statistics.Clear(); return; + } Statistics = JsonConvert.DeserializeObject>(value); } @@ -95,5 +120,13 @@ namespace osu.Game.Scoring public List Files { get; set; } public bool DeletePending { get; set; } + + [Serializable] + protected class DeserializedMod : Mod + { + public override string Name { get; } = string.Empty; + public override string ShortenedName { get; } = string.Empty; + public override double ScoreMultiplier { get; } = 0; + } } } diff --git a/osu.Game/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs index eeef9894bf..8b99bc0e8d 100644 --- a/osu.Game/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -18,7 +18,7 @@ namespace osu.Game.Scoring protected override IQueryable AddIncludesForConsumption(IQueryable query) => base.AddIncludesForConsumption(query) .Include(s => s.Files).ThenInclude(f => f.FileInfo) - .Include(s => s.BeatmapInfo) + .Include(s => s.Beatmap) .Include(s => s.Ruleset); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fe649ae35b..24592ebedc 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -275,7 +275,7 @@ namespace osu.Game.Screens.Play var score = new ScoreInfo { - BeatmapInfo = Beatmap.Value.BeatmapInfo, + Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset }; ScoreProcessor.PopulateScore(score); diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index 6db34fc071..c5a5cc6ad9 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.Centre, Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Beatmap = Beatmap.BeatmapInfo ?? Score.BeatmapInfo, + Beatmap = Beatmap.BeatmapInfo ?? Score.Beatmap, Scale = new Vector2(0.7f) } }; From 58293c3eae6189fd8d29d88a48022d539e3bf960 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 16:35:57 +0900 Subject: [PATCH 53/76] Re-migrate --- ...> 20181130071705_AddScoreInfoTables.Designer.cs} | 13 ++++++++----- ...bles.cs => 20181130071705_AddScoreInfoTables.cs} | 6 +++--- osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 11 +++++++---- 3 files changed, 18 insertions(+), 12 deletions(-) rename osu.Game/Migrations/{20181130052804_AddScoreInfoTables.Designer.cs => 20181130071705_AddScoreInfoTables.Designer.cs} (97%) rename osu.Game/Migrations/{20181130052804_AddScoreInfoTables.cs => 20181130071705_AddScoreInfoTables.cs} (95%) diff --git a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs similarity index 97% rename from osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs rename to osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs index 273c4fbdaa..25c475d64e 100644 --- a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs @@ -9,7 +9,7 @@ using osu.Game.Database; namespace osu.Game.Migrations { [DbContext(typeof(OsuDbContext))] - [Migration("20181130052804_AddScoreInfoTables")] + [Migration("20181130071705_AddScoreInfoTables")] partial class AddScoreInfoTables { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -325,7 +325,8 @@ namespace osu.Game.Migrations b.Property("MaxCombo"); - b.Property("ModsString"); + b.Property("ModsJson") + .HasColumnName("Mods"); b.Property("OnlineScoreID"); @@ -335,11 +336,13 @@ namespace osu.Game.Migrations b.Property("RulesetID"); - b.Property("StatisticsString"); + b.Property("StatisticsJson") + .HasColumnName("Statistics"); b.Property("TotalScore"); - b.Property("UserString"); + b.Property("UserString") + .HasColumnName("User"); b.HasKey("ID"); @@ -446,7 +449,7 @@ namespace osu.Game.Migrations modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => { - b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "BeatmapInfo") + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") .WithMany() .HasForeignKey("BeatmapInfoID") .OnDelete(DeleteBehavior.Cascade); diff --git a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs b/osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs similarity index 95% rename from osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs rename to osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs index 470f541c32..48927cd86e 100644 --- a/osu.Game/Migrations/20181130052804_AddScoreInfoTables.cs +++ b/osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs @@ -21,12 +21,12 @@ namespace osu.Game.Migrations MaxCombo = table.Column(nullable: false), Combo = table.Column(nullable: false), RulesetID = table.Column(nullable: false), - ModsString = table.Column(nullable: true), - UserString = table.Column(nullable: true), + Mods = table.Column(nullable: true), + User = table.Column(nullable: true), BeatmapInfoID = table.Column(nullable: false), OnlineScoreID = table.Column(nullable: true), Date = table.Column(nullable: false), - StatisticsString = table.Column(nullable: true), + Statistics = table.Column(nullable: true), MD5Hash = table.Column(nullable: true), DeletePending = table.Column(nullable: false) }, diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index c44fdcf8dd..abd6c43499 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -323,7 +323,8 @@ namespace osu.Game.Migrations b.Property("MaxCombo"); - b.Property("ModsString"); + b.Property("ModsJson") + .HasColumnName("Mods"); b.Property("OnlineScoreID"); @@ -333,11 +334,13 @@ namespace osu.Game.Migrations b.Property("RulesetID"); - b.Property("StatisticsString"); + b.Property("StatisticsJson") + .HasColumnName("Statistics"); b.Property("TotalScore"); - b.Property("UserString"); + b.Property("UserString") + .HasColumnName("User"); b.HasKey("ID"); @@ -444,7 +447,7 @@ namespace osu.Game.Migrations modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => { - b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "BeatmapInfo") + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") .WithMany() .HasForeignKey("BeatmapInfoID") .OnDelete(DeleteBehavior.Cascade); From e82ad3539b6b0ea59fa551f83195fb8d461e2907 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 16:39:25 +0900 Subject: [PATCH 54/76] Move JsonIgnore specification to interface --- osu.Game/Beatmaps/BeatmapDifficulty.cs | 2 -- osu.Game/Beatmaps/BeatmapInfo.cs | 2 -- osu.Game/Database/IHasPrimaryKey.cs | 2 ++ osu.Game/Rulesets/RulesetInfo.cs | 3 --- osu.Game/Scoring/ScoreInfo.cs | 1 - 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index a6d69f322d..418bcb5ad1 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using Newtonsoft.Json; using osu.Game.Database; namespace osu.Game.Beatmaps @@ -13,7 +12,6 @@ namespace osu.Game.Beatmaps /// public const float DEFAULT_DIFFICULTY = 5; - [JsonIgnore] public int ID { get; set; } public float DrainRate { get; set; } = DEFAULT_DIFFICULTY; diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 7479e1bbdb..9f6e7f11c6 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -15,7 +15,6 @@ namespace osu.Game.Beatmaps [Serializable] public class BeatmapInfo : IEquatable, IJsonSerializable, IHasPrimaryKey { - [JsonIgnore] public int ID { get; set; } public int BeatmapVersion; @@ -29,7 +28,6 @@ namespace osu.Game.Beatmaps set => onlineBeatmapID = value > 0 ? value : null; } - [JsonIgnore] public int BeatmapSetInfoID { get; set; } public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index 71e8867fa7..c62e78ea23 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.cs @@ -2,11 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; namespace osu.Game.Database { public interface IHasPrimaryKey { + [JsonIgnore] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] int ID { get; set; } } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index a6a311f6eb..6c21b9fd2f 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,15 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; namespace osu.Game.Rulesets { public class RulesetInfo : IEquatable { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [JsonIgnore] public int? ID { get; set; } public string Name { get; set; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 62d9ca7c2c..8ca5637be4 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -17,7 +17,6 @@ namespace osu.Game.Scoring { public class ScoreInfo : IHasFiles, IHasPrimaryKey, ISoftDelete { - [JsonIgnore] public int ID { get; set; } public ScoreRank Rank { get; set; } From 10095d09c341b84542532343d97786cb660095cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:02:01 +0900 Subject: [PATCH 55/76] Fix test namespace --- osu.Game.Tests/{Beatmaps => Scores}/IO/ImportScoreTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/{Beatmaps => Scores}/IO/ImportScoreTest.cs (99%) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs similarity index 99% rename from osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs rename to osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 76ebbef784..943b62a4fa 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; -namespace osu.Game.Tests.Beatmaps.IO +namespace osu.Game.Tests.Scores.IO { public class ImportScoreTest { From 84f3d4f48d60d3d8b2e10fa5d03cbfdfb6e5d32e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:15:32 +0900 Subject: [PATCH 56/76] Fix nullref --- osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 13633ce1e1..a7c9dbcd86 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -107,7 +107,8 @@ namespace osu.Game.Online.API.Requests.Responses set { base.Beatmap = value; - Ruleset = value.Ruleset; + if (Beatmap.Ruleset != null) + Ruleset = value.Ruleset; } } From d97a15a504a11ab2940c9ba68daefb85fca2c6bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:16:00 +0900 Subject: [PATCH 57/76] Add IMod and change ShortenedName to Acronym --- osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 2 +- .../DifficultyAdjustmentModCombinationsTest.cs | 8 ++++---- osu.Game.Tests/Visual/TestCasePlaySongSelect.cs | 2 +- .../Online/API/Requests/Responses/APIScoreInfo.cs | 2 +- osu.Game/Rulesets/Mods/IMod.cs | 10 ++++++++++ osu.Game/Rulesets/Mods/Mod.cs | 4 ++-- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Rulesets/Mods/ModCinema.cs | 2 +- osu.Game/Rulesets/Mods/ModDaycore.cs | 2 +- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 2 +- osu.Game/Rulesets/Mods/ModEasy.cs | 2 +- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 +- osu.Game/Rulesets/Mods/ModHalfTime.cs | 2 +- osu.Game/Rulesets/Mods/ModHardRock.cs | 2 +- osu.Game/Rulesets/Mods/ModHidden.cs | 2 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 2 +- osu.Game/Rulesets/Mods/ModNoFail.cs | 2 +- osu.Game/Rulesets/Mods/ModPerfect.cs | 2 +- osu.Game/Rulesets/Mods/ModRelax.cs | 2 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 +- osu.Game/Rulesets/Mods/MultiMod.cs | 2 +- osu.Game/Rulesets/Mods/NoModMod.cs | 2 +- osu.Game/Scoring/ScoreInfo.cs | 12 +++++------- 41 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IMod.cs diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index 6d91c03c13..d4164ec1f6 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter { - public override string ShortenedName => Name; + public override string Acronym => Name; public abstract int KeyCount { get; } public override ModType Type => ModType.Conversion; public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index 4790a77cc0..5a8ce05873 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToBeatmap { public override string Name => "Dual Stages"; - public override string ShortenedName => "DS"; + public override string Acronym => "DS"; public override string Description => @"Double the stages, double the fun!"; public override ModType Type => ModType.Conversion; public override double ScoreMultiplier => 1; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs index 73942cbb53..229170cea8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModFadeIn : Mod { public override string Name => "Fade In"; - public override string ShortenedName => "FI"; + public override string Acronym => "FI"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; public override ModType Type => ModType.DifficultyIncrease; public override string Description => @"Keys appear out of nowhere!"; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs index c2a4ed444f..11143f715e 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 1; public override string Name => "One Key"; - public override string ShortenedName => "1K"; + public override string Acronym => "1K"; public override string Description => @"Play with one key."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs index 3d78ad449b..0169d4ecac 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 2; public override string Name => "Two Keys"; - public override string ShortenedName => "2K"; + public override string Acronym => "2K"; public override string Description => @"Play with two keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs index a96375a81d..12e84eda0f 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 3; public override string Name => "Three Keys"; - public override string ShortenedName => "3K"; + public override string Acronym => "3K"; public override string Description => @"Play with three keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs index 2bd3d08648..ab5ed91d9d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 4; public override string Name => "Four Keys"; - public override string ShortenedName => "4K"; + public override string Acronym => "4K"; public override string Description => @"Play with four keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs index e59b2d6e59..be9f0f8066 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 5; public override string Name => "Five Keys"; - public override string ShortenedName => "5K"; + public override string Acronym => "5K"; public override string Description => @"Play with five keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs index 6a05317f46..571e533078 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 6; public override string Name => "Six Keys"; - public override string ShortenedName => "6K"; + public override string Acronym => "6K"; public override string Description => @"Play with six keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs index 7280c345b8..89c6bd997d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 7; public override string Name => "Seven Keys"; - public override string ShortenedName => "7K"; + public override string Acronym => "7K"; public override string Description => @"Play with seven keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs index dddef0fa9d..8d043651d3 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 8; public override string Name => "Eight Keys"; - public override string ShortenedName => "8K"; + public override string Acronym => "8K"; public override string Description => @"Play with eight keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs index 4ef38503a4..20471ebffc 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public override int KeyCount => 9; public override string Name => "Nine Keys"; - public override string ShortenedName => "9K"; + public override string Acronym => "9K"; public override string Description => @"Play with nine keys."; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index 847b0037f1..68325b40bf 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModMirror : Mod, IApplicableToRulesetContainer { public override string Name => "Mirror"; - public override string ShortenedName => "MR"; + public override string Acronym => "MR"; public override ModType Type => ModType.Conversion; public override double ScoreMultiplier => 1; public override bool Ranked => true; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index 0915b80742..b3a3d4280b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModRandom : Mod, IApplicableToRulesetContainer { public override string Name => "Random"; - public override string ShortenedName => "RD"; + public override string Acronym => "RD"; public override ModType Type => ModType.Conversion; public override FontAwesome Icon => FontAwesome.fa_osu_dice; public override string Description => @"Shuffle around the keys!"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 37d5f57fcb..4d371c2e16 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModAutopilot : Mod { public override string Name => "Autopilot"; - public override string ShortenedName => "AP"; + public override string Acronym => "AP"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; public override ModType Type => ModType.Automation; public override string Description => @"Automatic cursor movement - just follow the rhythm."; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index 6aa864d9b2..cf0d629367 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModSpunOut : Mod { public override string Name => "Spun Out"; - public override string ShortenedName => "SO"; + public override string Acronym => "SO"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; public override ModType Type => ModType.DifficultyReduction; public override string Description => @"Spinners will be automatically completed."; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index 139ce4cc4b..968854d8b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModTarget : Mod { public override string Name => "Target"; - public override string ShortenedName => "TP"; + public override string Acronym => "TP"; public override ModType Type => ModType.Conversion; public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; public override string Description => @"Practice keeping up with the beat of the song."; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index dcd1896601..6949f44bd1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects { public override string Name => "Transform"; - public override string ShortenedName => "TR"; + public override string Acronym => "TR"; public override FontAwesome Icon => FontAwesome.fa_arrows; public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING."; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 93f1070231..3f7d43e31f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects { public override string Name => "Wiggle"; - public override string ShortenedName => "WG"; + public override string Acronym => "WG"; public override FontAwesome Icon => FontAwesome.fa_certificate; public override ModType Type => ModType.Fun; public override string Description => "They just won't stay still..."; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 49494b65b9..66d372727a 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.NonVisual private class ModA : Mod { public override string Name => nameof(ModA); - public override string ShortenedName => nameof(ModA); + public override string Acronym => nameof(ModA); public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) }; @@ -103,7 +103,7 @@ namespace osu.Game.Tests.NonVisual private class ModB : Mod { public override string Name => nameof(ModB); - public override string ShortenedName => nameof(ModB); + public override string Acronym => nameof(ModB); public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) }; @@ -112,7 +112,7 @@ namespace osu.Game.Tests.NonVisual private class ModIncompatibleWithA : Mod { public override string Name => $"Incompatible With {nameof(ModA)}"; - public override string ShortenedName => $"Incompatible With {nameof(ModA)}"; + public override string Acronym => $"Incompatible With {nameof(ModA)}"; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModA) }; @@ -130,7 +130,7 @@ namespace osu.Game.Tests.NonVisual private class ModIncompatibleWithAAndB : Mod { public override string Name => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; - public override string ShortenedName => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; + public override string Acronym => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index 888bf6250f..87235add37 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual private static int importId; private int getImportId() => ++importId; - private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.ShortenedName))}", () => selectedMods.Value = mods); + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => selectedMods.Value = mods); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index a7c9dbcd86..5d34b8eff5 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -120,7 +120,7 @@ namespace osu.Game.Online.API.Requests.Responses base.Ruleset = value; // Evaluate the mod string - Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray(); + Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.Acronym)).ToArray(); } } } diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs new file mode 100644 index 0000000000..e8d0290775 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -0,0 +1,10 @@ +namespace osu.Game.Rulesets.Mods +{ + public interface IMod + { + /// + /// The shortened name of this mod. + /// + string Acronym { get; } + } +} diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 81ebca2fe3..14ee6b99ec 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods /// /// The base class for gameplay modifiers. /// - public abstract class Mod : IJsonSerializable + public abstract class Mod : IMod, IJsonSerializable { /// /// The name of this mod. @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mods /// /// The shortened name of this mod. /// - public abstract string ShortenedName { get; } + public abstract string Acronym { get; } /// /// The icon of this mod. diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 3f3cab5854..932439618d 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModAutoplay : Mod, IApplicableFailOverride { public override string Name => "Autoplay"; - public override string ShortenedName => "AT"; + public override string Acronym => "AT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override ModType Type => ModType.Automation; public override string Description => "Watch a perfect automated play through the song."; diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 421e3a54e4..5c4040ee4c 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods public class ModCinema : ModAutoplay { public override string Name => "Cinema"; - public override string ShortenedName => "CN"; + public override string Acronym => "CN"; public override bool HasImplementation => false; public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; public override string Description => "Watch the video without visual distractions."; diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index f11d0c76ed..5e3ec60be3 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModDaycore : ModHalfTime { public override string Name => "Daycore"; - public override string ShortenedName => "DC"; + public override string Acronym => "DC"; public override FontAwesome Icon => FontAwesome.fa_question; public override string Description => "Whoaaaaa..."; diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 0d44495fce..5c1d732995 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModDoubleTime : Mod, IApplicableToClock { public override string Name => "Double Time"; - public override string ShortenedName => "DT"; + public override string Acronym => "DT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Zoooooooooom..."; diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 93abb82e5b..03781bea47 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModEasy : Mod, IApplicableToDifficulty { public override string Name => "Easy"; - public override string ShortenedName => "EZ"; + public override string Acronym => "EZ"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy; public override ModType Type => ModType.DifficultyReduction; public override double ScoreMultiplier => 0.5; diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 755daf359a..98da97d6fe 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModFlashlight : Mod { public override string Name => "Flashlight"; - public override string ShortenedName => "FL"; + public override string Acronym => "FL"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Restricted view area."; diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 3ec4fb9f9f..2d95b10db1 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModHalfTime : Mod, IApplicableToClock { public override string Name => "Half Time"; - public override string ShortenedName => "HT"; + public override string Acronym => "HT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime; public override ModType Type => ModType.DifficultyReduction; public override string Description => "Less zoom..."; diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 6379be9bfc..14f997ae8c 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModHardRock : Mod, IApplicableToDifficulty { public override string Name => "Hard Rock"; - public override string ShortenedName => "HR"; + public override string Acronym => "HR"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Everything just got a bit harder..."; diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 9b09f0bd6d..b843171521 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModHidden : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Hidden"; - public override string ShortenedName => "HD"; + public override string Acronym => "HD"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; public override ModType Type => ModType.DifficultyIncrease; public override bool Ranked => true; diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 162d654965..f4fe1c3831 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModNightcore : ModDoubleTime { public override string Name => "Nightcore"; - public override string ShortenedName => "NC"; + public override string Acronym => "NC"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore; public override string Description => "Uguuuuuuuu..."; diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 7510f62432..223af7d304 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModNoFail : Mod, IApplicableFailOverride { public override string Name => "No Fail"; - public override string ShortenedName => "NF"; + public override string Acronym => "NF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; public override ModType Type => ModType.DifficultyReduction; public override string Description => "You can't fail, no matter what."; diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 802890866f..b7ded41024 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModPerfect : ModSuddenDeath { public override string Name => "Perfect"; - public override string ShortenedName => "PF"; + public override string Acronym => "PF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_perfect; public override string Description => "SS or quit."; diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index 04aa295893..769cde6746 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModRelax : Mod { public override string Name => "Relax"; - public override string ShortenedName => "RX"; + public override string Acronym => "RX"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax; public override ModType Type => ModType.Automation; public override double ScoreMultiplier => 1; diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 48f7d496a5..77d411d8fd 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor { public override string Name => "Sudden Death"; - public override string ShortenedName => "SD"; + public override string Acronym => "SD"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Miss and fail."; diff --git a/osu.Game/Rulesets/Mods/MultiMod.cs b/osu.Game/Rulesets/Mods/MultiMod.cs index b65773e93f..26e09a59e0 100644 --- a/osu.Game/Rulesets/Mods/MultiMod.cs +++ b/osu.Game/Rulesets/Mods/MultiMod.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods public class MultiMod : Mod { public override string Name => string.Empty; - public override string ShortenedName => string.Empty; + public override string Acronym => string.Empty; public override string Description => string.Empty; public override double ScoreMultiplier => 0; diff --git a/osu.Game/Rulesets/Mods/NoModMod.cs b/osu.Game/Rulesets/Mods/NoModMod.cs index dcab3538da..0631054690 100644 --- a/osu.Game/Rulesets/Mods/NoModMod.cs +++ b/osu.Game/Rulesets/Mods/NoModMod.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods public sealed class NoModMod : Mod { public override string Name => "No Mod"; - public override string ShortenedName => "NM"; + public override string Acronym => "NM"; public override double ScoreMultiplier => 1; } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 8ca5637be4..bd8a8901d7 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -53,19 +53,19 @@ namespace osu.Game.Scoring } set { + modsJson = null; mods = value; - ModsJson = null; } } - private Mod[] getModsFromRuleset(DeserializedMod[] mods) => Ruleset.CreateInstance().GetAllMods().Where(mod => mods.Any(d => d.ShortenedName == mod.ShortenedName)).ToArray(); + private Mod[] getModsFromRuleset(DeserializedMod[] mods) => Ruleset.CreateInstance().GetAllMods().Where(mod => mods.Any(d => d.Acronym == mod.Acronym)).ToArray(); private string modsJson; [Column("Mods")] public string ModsJson { - get => modsJson ?? JsonConvert.SerializeObject(Mods); + get => modsJson ?? (modsJson = JsonConvert.SerializeObject(mods)); set { modsJson = value; @@ -121,11 +121,9 @@ namespace osu.Game.Scoring public bool DeletePending { get; set; } [Serializable] - protected class DeserializedMod : Mod + protected class DeserializedMod : IMod { - public override string Name { get; } = string.Empty; - public override string ShortenedName { get; } = string.Empty; - public override double ScoreMultiplier { get; } = 0; + public string Acronym { get; set; } } } } From be37f3c3282ae72825cb235ea140ec2a88087ade Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:35:13 +0900 Subject: [PATCH 58/76] Rename NoModMod --- .../DifficultyAdjustmentModCombinationsTest.cs | 12 ++++++------ osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 2 +- osu.Game/Rulesets/Mods/{NoModMod.cs => ModNoMod.cs} | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Rulesets/Mods/{NoModMod.cs => ModNoMod.cs} (91%) diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 66d372727a..42fe4065c7 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(1, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); } [Test] @@ -27,7 +27,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(2, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); } @@ -37,7 +37,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(4, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[3] is ModB); @@ -52,7 +52,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is ModIncompatibleWithA); } @@ -63,7 +63,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(8, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[3] is ModB); @@ -86,7 +86,7 @@ namespace osu.Game.Tests.NonVisual var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); - Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModAofA); Assert.IsTrue(combinations[2] is ModIncompatibleWithAofA); } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 0de0a620e3..25fd49ff9b 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Difficulty { case 0: // Initial-case: Empty current set - yield return new NoModMod(); + yield return new ModNoMod(); break; case 1: yield return currentSet.Single(); diff --git a/osu.Game/Rulesets/Mods/NoModMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs similarity index 91% rename from osu.Game/Rulesets/Mods/NoModMod.cs rename to osu.Game/Rulesets/Mods/ModNoMod.cs index 0631054690..c75849149b 100644 --- a/osu.Game/Rulesets/Mods/NoModMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -6,7 +6,7 @@ namespace osu.Game.Rulesets.Mods /// /// Indicates a type of mod that doesn't do anything. /// - public sealed class NoModMod : Mod + public sealed class ModNoMod : Mod { public override string Name => "No Mod"; public override string Acronym => "NM"; From 66e43e6ed943b7501969a82ead1808fdc6aa8474 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:36:06 +0900 Subject: [PATCH 59/76] Update hashing method in line with master --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 8 ++------ osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 4 +++- osu.Game/Scoring/ScoreInfo.cs | 8 ++------ osu.Game/Scoring/ScoreManager.cs | 18 ++---------------- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 943b62a4fa..9c1c631566 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -121,10 +121,8 @@ namespace osu.Game.Tests.Scores.IO } } - private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score, string guidOverride = null) + private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score) { - score.MD5Hash = guidOverride ?? Guid.NewGuid().ToString(); - var beatmapManager = osu.Dependencies.Get(); score.Beatmap = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); @@ -133,9 +131,7 @@ namespace osu.Game.Tests.Scores.IO var scoreManager = osu.Dependencies.Get(); scoreManager.Import(score); - var imported = scoreManager.Query(s => s.MD5Hash == score.MD5Hash); - - return imported; + return scoreManager.GetAllUsableScores().First(); } private string createTemporaryBeatmap() diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index edc8ed65d8..caa32020cc 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -46,7 +46,9 @@ namespace osu.Game.Scoring.Legacy score.ScoreInfo.Beatmap = currentBeatmap.BeatmapInfo; score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; - score.ScoreInfo.MD5Hash = sr.ReadString(); + + // MD5Hash + sr.ReadString(); var count300 = (int)sr.ReadUInt16(); var count100 = (int)sr.ReadUInt16(); diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index bd8a8901d7..2f1c924707 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -110,14 +110,10 @@ namespace osu.Game.Scoring } } - /// - /// MD5 is kept for legacy support. - /// - [JsonProperty("file_md5")] - public string MD5Hash { get; set; } - public List Files { get; set; } + public string Hash { get; set; } + public bool DeletePending { get; set; } [Serializable] diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 5d16d40346..a2f156f6c3 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -20,20 +20,18 @@ namespace osu.Game.Scoring { public override string[] HandledExtensions => new[] { ".osr" }; + protected override string[] HashableFileTypes => new[] { ".osr" }; + protected override string ImportFromStablePath => "Replays"; private readonly RulesetStore rulesets; private readonly BeatmapManager beatmaps; - private readonly ScoreStore scores; - public ScoreManager(RulesetStore rulesets, BeatmapManager beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) : base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) { this.rulesets = rulesets; this.beatmaps = beatmaps; - - scores = (ScoreStore)ModelStore; } protected override ScoreInfo CreateModel(ArchiveReader archive) @@ -55,18 +53,6 @@ namespace osu.Game.Scoring } } - protected override ScoreInfo CheckForExisting(ScoreInfo model) - { - var existingHashMatch = scores.ConsumableItems.FirstOrDefault(s => s.MD5Hash != null && s.MD5Hash == model.MD5Hash); - if (existingHashMatch != null) - { - Undelete(existingHashMatch); - return existingHashMatch; - } - - return null; - } - public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps, Files.Store); public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); From 00c5ea28c7b9fa9a73fd7b56069812dcf957f4cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:42:40 +0900 Subject: [PATCH 60/76] Update migrations in line with hash change --- ...> 20181130084152_AddScoreInfoTables.Designer.cs} | 13 ++++++++++--- ...bles.cs => 20181130084152_AddScoreInfoTables.cs} | 2 +- osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) rename osu.Game/Migrations/{20181130071705_AddScoreInfoTables.Designer.cs => 20181130084152_AddScoreInfoTables.Designer.cs} (98%) rename osu.Game/Migrations/{20181130071705_AddScoreInfoTables.cs => 20181130084152_AddScoreInfoTables.cs} (98%) diff --git a/osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130084152_AddScoreInfoTables.Designer.cs similarity index 98% rename from osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs rename to osu.Game/Migrations/20181130084152_AddScoreInfoTables.Designer.cs index 25c475d64e..99833268f9 100644 --- a/osu.Game/Migrations/20181130071705_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130084152_AddScoreInfoTables.Designer.cs @@ -9,7 +9,7 @@ using osu.Game.Database; namespace osu.Game.Migrations { [DbContext(typeof(OsuDbContext))] - [Migration("20181130071705_AddScoreInfoTables")] + [Migration("20181130084152_AddScoreInfoTables")] partial class AddScoreInfoTables { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -319,9 +319,9 @@ namespace osu.Game.Migrations b.Property("DeletePending"); - b.Property("Health"); + b.Property("Hash"); - b.Property("MD5Hash"); + b.Property("Health"); b.Property("MaxCombo"); @@ -386,10 +386,17 @@ namespace osu.Game.Migrations b.Property("DeletePending"); + b.Property("Hash"); + b.Property("Name"); b.HasKey("ID"); + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + b.ToTable("SkinInfo"); }); diff --git a/osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs b/osu.Game/Migrations/20181130084152_AddScoreInfoTables.cs similarity index 98% rename from osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs rename to osu.Game/Migrations/20181130084152_AddScoreInfoTables.cs index 48927cd86e..e45776abca 100644 --- a/osu.Game/Migrations/20181130071705_AddScoreInfoTables.cs +++ b/osu.Game/Migrations/20181130084152_AddScoreInfoTables.cs @@ -27,7 +27,7 @@ namespace osu.Game.Migrations OnlineScoreID = table.Column(nullable: true), Date = table.Column(nullable: false), Statistics = table.Column(nullable: true), - MD5Hash = table.Column(nullable: true), + Hash = table.Column(nullable: true), DeletePending = table.Column(nullable: false) }, constraints: table => diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index ba45fa9e36..a88dfc4a46 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -317,9 +317,9 @@ namespace osu.Game.Migrations b.Property("DeletePending"); - b.Property("Health"); + b.Property("Hash"); - b.Property("MD5Hash"); + b.Property("Health"); b.Property("MaxCombo"); From 2dd5dad7c5c64cf9de3b05700326b90b6bef9cda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:48:54 +0900 Subject: [PATCH 61/76] Remove empty lines --- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index caa32020cc..7fc0d97f9b 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -145,7 +145,6 @@ namespace osu.Game.Scoring.Legacy score.Rank = ScoreRank.C; else score.Rank = ScoreRank.D; - break; } case 1: @@ -168,7 +167,6 @@ namespace osu.Game.Scoring.Legacy score.Rank = ScoreRank.C; else score.Rank = ScoreRank.D; - break; } case 2: From 9718e476c7e4ea6eadc2547b4143243bd2f16b52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 17:50:27 +0900 Subject: [PATCH 62/76] Add license header --- osu.Game/Rulesets/Mods/IMod.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index e8d0290775..d0c4ce2f4c 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -1,4 +1,7 @@ -namespace osu.Game.Rulesets.Mods +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods { public interface IMod { From 059e9e180b92c79c9ffd0992bf6e26e354ddce50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 18:06:48 +0900 Subject: [PATCH 63/76] Apply review --- osu.Game/Beatmaps/BeatmapInfo.cs | 1 + osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs | 7 +++++-- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 3 --- osu.Game/Scoring/ScoreInfo.cs | 4 ++++ 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 9f6e7f11c6..0534fd9253 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -28,6 +28,7 @@ namespace osu.Game.Beatmaps set => onlineBeatmapID = value > 0 ? value : null; } + [JsonIgnore] public int BeatmapSetInfoID { get; set; } public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 5d34b8eff5..de7038cbde 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -119,8 +119,11 @@ namespace osu.Game.Online.API.Requests.Responses { base.Ruleset = value; - // Evaluate the mod string - Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.Acronym)).ToArray(); + if (modStrings != null) + { + // Evaluate the mod string + Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.Acronym)).ToArray(); + } } } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 441cb2c29f..f92990fc5d 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -9,7 +9,6 @@ using osu.Game.Users; using System; using System.Linq; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Scoring; namespace osu.Game.Overlays.Profile.Sections.Ranks { @@ -30,8 +29,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Direction = FillDirection.Vertical; } - private ScoreManager scoreManager; - protected override void ShowMore() { base.ShowMore(); diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2f1c924707..07f1181a69 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -75,6 +75,7 @@ namespace osu.Game.Scoring } } + [JsonIgnore] public User User; [Column("User")] @@ -84,6 +85,7 @@ namespace osu.Game.Scoring set => User = new User { Username = value }; } + [JsonIgnore] public int BeatmapInfoID { get; set; } public virtual BeatmapInfo Beatmap { get; set; } @@ -92,6 +94,7 @@ namespace osu.Game.Scoring public DateTimeOffset Date { get; set; } + [JsonIgnore] public Dictionary Statistics = new Dictionary(); [Column("Statistics")] @@ -110,6 +113,7 @@ namespace osu.Game.Scoring } } + [JsonIgnore] public List Files { get; set; } public string Hash { get; set; } From ed679846388c4d6104cf7b5f527ddc38d1ce3ff3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 13:06:48 +0900 Subject: [PATCH 64/76] Don't load player if score has no replay data --- osu.Game/OsuGame.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index eeeb24d7d4..a373be32a9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -267,15 +267,17 @@ namespace osu.Game return; } - var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == score.Beatmap.ID); + var score = ScoreManager.GetScore(scoreInfo); + if (score.Replay == null) + { + Logger.Log("The loaded score has no replay data.", LoggingTarget.Information); + return; + } + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); if (databasedBeatmap == null) { - notifications.Post(new SimpleNotification - { - Text = @"Tried to load a score for a beatmap we don't have!", - Icon = FontAwesome.fa_life_saver, - }); + Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); return; } @@ -284,7 +286,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); Beatmap.Value.Mods.Value = score.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(score).Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); } protected override void Dispose(bool isDisposing) From 8eff49bccdabc3c345bb4f23244f69fb51c4eedb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 13:22:45 +0900 Subject: [PATCH 65/76] Remove User from Replay --- .../Replays/CatchAutoGenerator.cs | 3 +-- .../Replays/ManiaAutoGenerator.cs | 3 +-- osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 2 ++ .../Replays/OsuAutoGeneratorBase.cs | 9 +------- .../Replays/TaikoAutoGenerator.cs | 9 +------- osu.Game.Tests/Visual/TestCaseReplay.cs | 6 ++--- osu.Game/OsuGame.cs | 2 +- osu.Game/Replays/Replay.cs | 2 -- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 2 +- osu.Game/Screens/Play/Player.cs | 23 ++++++++++++------- osu.Game/Screens/Play/ReplayPlayer.cs | 12 ++++++---- 11 files changed, 32 insertions(+), 41 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index b0376b547d..20bf2ee5c7 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -9,7 +9,6 @@ using osu.Game.Replays; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Replays; -using osu.Game.Users; namespace osu.Game.Rulesets.Catch.Replays { @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Replays public CatchAutoGenerator(Beatmap beatmap) : base(beatmap) { - Replay = new Replay { User = new User { Username = @"Autoplay" } }; + Replay = new Replay(); } protected Replay Replay; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 52672e6f17..c58d66c66a 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -8,7 +8,6 @@ using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; -using osu.Game.Users; namespace osu.Game.Rulesets.Mania.Replays { @@ -23,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaAutoGenerator(ManiaBeatmap beatmap) : base(beatmap) { - Replay = new Replay { User = new User { Username = @"Autoplay" } }; + Replay = new Replay(); columnActions = new ManiaAction[Beatmap.TotalColumns]; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index ce5d3dae44..7ef01e075c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Scoring; +using osu.Game.Users; namespace osu.Game.Rulesets.Osu.Mods { @@ -17,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected override Score CreateReplayScore(Beatmap beatmap) => new Score { + ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } }, Replay = new OsuAutoGenerator(beatmap).Generate() }; } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 12d130ef53..6dc5e42258 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using osu.Game.Replays; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Replays; -using osu.Game.Users; namespace osu.Game.Rulesets.Osu.Replays { @@ -38,13 +37,7 @@ namespace osu.Game.Rulesets.Osu.Replays protected OsuAutoGeneratorBase(Beatmap beatmap) : base(beatmap) { - Replay = new Replay - { - User = new User - { - Username = @"Autoplay", - } - }; + Replay = new Replay(); // We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps. FrameDelay = ApplyModsToRate(1000.0 / 60.0); diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index f089877f38..2794a3c166 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -9,7 +9,6 @@ using osu.Game.Replays; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; -using osu.Game.Users; namespace osu.Game.Rulesets.Taiko.Replays { @@ -20,13 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Replays public TaikoAutoGenerator(Beatmap beatmap) : base(beatmap) { - Replay = new Replay - { - User = new User - { - Username = @"Autoplay", - } - }; + Replay = new Replay(); } protected Replay Replay; diff --git a/osu.Game.Tests/Visual/TestCaseReplay.cs b/osu.Game.Tests/Visual/TestCaseReplay.cs index 1f2d99a7d8..e0ea613534 100644 --- a/osu.Game.Tests/Visual/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/TestCaseReplay.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Linq; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual @@ -19,13 +20,10 @@ namespace osu.Game.Tests.Visual Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(Beatmap.Value); - // We have the replay - var replay = dummyRulesetContainer.Replay; - // Reset the mods Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Where(m => !(m is ModAutoplay)); - return new ReplayPlayer(replay); + return new ReplayPlayer(new Score { Replay = dummyRulesetContainer.Replay }); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a373be32a9..302509423f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -286,7 +286,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); Beatmap.Value.Mods.Value = score.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(score))); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Replays/Replay.cs b/osu.Game/Replays/Replay.cs index 966849c783..bb6d9e7637 100644 --- a/osu.Game/Replays/Replay.cs +++ b/osu.Game/Replays/Replay.cs @@ -3,13 +3,11 @@ using System.Collections.Generic; using osu.Game.Rulesets.Replays; -using osu.Game.Users; namespace osu.Game.Replays { public class Replay { - public User User; public List Frames = new List(); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 7fc0d97f9b..13fe021f95 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -45,7 +45,7 @@ namespace osu.Game.Scoring.Legacy currentBeatmap = workingBeatmap.Beatmap; score.ScoreInfo.Beatmap = currentBeatmap.BeatmapInfo; - score.ScoreInfo.User = score.Replay.User = new User { Username = sr.ReadString() }; + score.ScoreInfo.User = new User { Username = sr.ReadString() }; // MD5Hash sr.ReadString(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 24592ebedc..e10bd1fd69 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -273,20 +273,27 @@ namespace osu.Game.Screens.Play { if (!IsCurrentScreen) return; - var score = new ScoreInfo - { - Beatmap = Beatmap.Value.BeatmapInfo, - Ruleset = ruleset - }; - ScoreProcessor.PopulateScore(score); - score.User = RulesetContainer.Replay?.User ?? api.LocalUser.Value; - Push(new Results(score)); + Push(new Results(CreateScoreInfo())); onCompletionEvent = null; }); } } + protected virtual ScoreInfo CreateScoreInfo() + { + var score = new ScoreInfo + { + BeatmapInfo = Beatmap.Value.BeatmapInfo, + Ruleset = ruleset, + User = api.LocalUser.Value + }; + + ScoreProcessor.PopulateScore(score); + + return score; + } + private bool onFail() { if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 9204a49ac9..508933052a 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,23 +1,25 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Replays; +using osu.Game.Scoring; namespace osu.Game.Screens.Play { public class ReplayPlayer : Player { - public Replay Replay; + private readonly Score score; - public ReplayPlayer(Replay replay) + public ReplayPlayer(Score score) { - Replay = replay; + this.score = score; } protected override void LoadComplete() { base.LoadComplete(); - RulesetContainer.SetReplay(Replay); + RulesetContainer.SetReplay(score.Replay); } + + protected override ScoreInfo CreateScoreInfo() => score.ScoreInfo; } } From 4c1abdcd8c82f07ca51ec0d27963592c7af96fa9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 14:56:29 +0900 Subject: [PATCH 66/76] Save score upon map completion --- osu.Game/Screens/Play/Player.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e10bd1fd69..c44fba0c69 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -67,6 +67,9 @@ namespace osu.Game.Screens.Play /// private DecoupleableInterpolatingFramedClock adjustableClock; + [Resolved] + private ScoreManager scoreManager { get; set; } + private PauseContainer pauseContainer; private RulesetInfo ruleset; @@ -273,7 +276,11 @@ namespace osu.Game.Screens.Play { if (!IsCurrentScreen) return; - Push(new Results(CreateScoreInfo())); + var score = CreateScoreInfo(); + if (RulesetContainer.Replay == null) + scoreManager.Import(score); + + Push(new Results(score)); onCompletionEvent = null; }); From d07a724970672a2f847253b41363c53f86f37b85 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 17:18:59 +0900 Subject: [PATCH 67/76] Only allow replay screen changes in menu + songselect --- osu.Game/OsuGame.cs | 48 +++++++++++++++++++-------- osu.Game/Screens/Menu/MainMenu.cs | 2 ++ osu.Game/Screens/OsuScreen.cs | 2 ++ osu.Game/Screens/Select/SongSelect.cs | 2 ++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 302509423f..26e587e5dd 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -260,13 +260,6 @@ namespace osu.Game return; } - if (!menu.IsCurrentScreen) - { - menu.MakeCurrent(); - this.Delay(500).Schedule(() => LoadScore(score), out scoreLoad); - return; - } - var score = ScoreManager.GetScore(scoreInfo); if (score.Replay == null) { @@ -274,19 +267,46 @@ namespace osu.Game return; } - var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); - if (databasedBeatmap == null) + if (!currentScreen.AllowExternalScreenChange) { - Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); + notifications.Post(new SimpleNotification + { + Text = $"Click here to watch {scoreInfo.User.Username} on {scoreInfo.BeatmapInfo}", + Activated = () => + { + loadScore(); + return true; + } + }); + return; } - ruleset.Value = score.Ruleset; + loadScore(); - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Beatmap.Value.Mods.Value = score.Mods; + void loadScore() + { + if (!menu.IsCurrentScreen) + { + menu.MakeCurrent(); + this.Delay(500).Schedule(loadScore, out scoreLoad); + return; + } - menu.Push(new PlayerLoader(new ReplayPlayer(score))); + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); + if (databasedBeatmap == null) + { + Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); + return; + } + + ruleset.Value = score.Ruleset; + + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); + Beatmap.Value.Mods.Value = score.Mods; + + currentScreen.Push(new PlayerLoader(new ReplayPlayer(score))); + } } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index cafd718055..974e42dda0 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -29,6 +29,8 @@ namespace osu.Game.Screens.Menu protected override bool AllowBackButton => buttons.State != ButtonSystemState.Initial; + public override bool AllowExternalScreenChange => true; + private readonly BackgroundScreenDefault background; private Screen songSelect; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 00309fbcd5..69f2b6ef9d 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens protected virtual bool AllowBackButton => true; + public virtual bool AllowExternalScreenChange => false; + /// /// Override to create a BackgroundMode for the current screen. /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause. diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 360032c37c..b8458c4c70 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -40,6 +40,8 @@ namespace osu.Game.Screens.Select protected virtual bool ShowFooter => true; + public override bool AllowExternalScreenChange => true; + /// /// Can be null if is false. /// From a8ad7d4670723e9f9e8a454fe0d88bed9f42faee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 18:07:51 +0900 Subject: [PATCH 68/76] Add silent import parameter --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 2 +- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 13 +++++++------ osu.Game/Database/MutableDatabaseBackedStore.cs | 13 ++++++++----- osu.Game/OsuGame.cs | 9 ++++++--- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 4 ++-- osu.Game/Overlays/MusicController.cs | 2 +- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 11 files changed, 30 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index fb6f735d2d..26167cb24a 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Beatmaps.IO int fireCount = 0; // ReSharper disable once AccessToModifiedClosure - manager.ItemAdded += (_, __) => fireCount++; + manager.ItemAdded += (_, __, ___) => fireCount++; manager.ItemRemoved += _ => fireCount++; var imported = loadOszIntoOsu(osu); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index f1920b43cc..baeeaf81a4 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps.Drawables } } - private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() => + private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) DownloadState.Value = DownloadStatus.Downloaded; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index a7c2aad260..b870b7dfc2 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -32,7 +32,7 @@ namespace osu.Game.Database where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { - public delegate void ItemAddedDelegate(TModel model, bool existing); + public delegate void ItemAddedDelegate(TModel model, bool existing, bool silent); /// /// Set an endpoint for notifications to be posted to. @@ -110,7 +110,7 @@ namespace osu.Game.Database ContextFactory = contextFactory; ModelStore = modelStore; - ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s, false)); + ModelStore.ItemAdded += (item, silent) => handleEvent(() => ItemAdded?.Invoke(item, false, silent)); ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s)); Files = new FileStore(contextFactory, storage); @@ -211,7 +211,7 @@ namespace osu.Game.Database model.Hash = computeHash(archive); - return Import(model, archive); + return Import(model, false, archive); } catch (Exception e) { @@ -245,8 +245,9 @@ namespace osu.Game.Database /// Import an item from a . /// /// The model to be imported. + /// Whether the user should be notified fo the import. /// An optional archive to use for model population. - public TModel Import(TModel item, ArchiveReader archive = null) + public TModel Import(TModel item, bool silent = false, ArchiveReader archive = null) { delayEvents(); @@ -266,7 +267,7 @@ namespace osu.Game.Database { Undelete(existing); Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); - handleEvent(() => ItemAdded?.Invoke(existing, true)); + handleEvent(() => ItemAdded?.Invoke(existing, true, silent)); return existing; } @@ -276,7 +277,7 @@ namespace osu.Game.Database Populate(item, archive); // import to store - ModelStore.Add(item); + ModelStore.Add(item, silent); } catch (Exception e) { diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index 69a1f57cc4..dc2fe54aac 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -16,7 +16,9 @@ namespace osu.Game.Database public abstract class MutableDatabaseBackedStore : DatabaseBackedStore where T : class, IHasPrimaryKey, ISoftDelete { - public event Action ItemAdded; + public delegate void ItemAddedDelegate(T model, bool silent); + + public event ItemAddedDelegate ItemAdded; public event Action ItemRemoved; protected MutableDatabaseBackedStore(IDatabaseContextFactory contextFactory, Storage storage = null) @@ -33,7 +35,8 @@ namespace osu.Game.Database /// Add a to the database. /// /// The item to add. - public void Add(T item) + /// Whether the user should be notified of the addition. + public void Add(T item, bool silent) { using (var usage = ContextFactory.GetForWrite()) { @@ -41,7 +44,7 @@ namespace osu.Game.Database context.Attach(item); } - ItemAdded?.Invoke(item); + ItemAdded?.Invoke(item, silent); } /// @@ -54,7 +57,7 @@ namespace osu.Game.Database usage.Context.Update(item); ItemRemoved?.Invoke(item); - ItemAdded?.Invoke(item); + ItemAdded?.Invoke(item, true); } /// @@ -89,7 +92,7 @@ namespace osu.Game.Database item.DeletePending = false; } - ItemAdded?.Invoke(item); + ItemAdded?.Invoke(item, true); return true; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 26e587e5dd..03ddc8da86 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -148,7 +148,7 @@ namespace osu.Game { this.frameworkConfig = frameworkConfig; - ScoreManager.ItemAdded += (score, _) => Schedule(() => LoadScore(score)); + ScoreManager.ItemAdded += (score, _, silent) => Schedule(() => LoadScore(score, silent)); if (!Host.IsPrimaryInstance) { @@ -248,15 +248,18 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); - protected void LoadScore(ScoreInfo score) + protected void LoadScore(ScoreInfo score, bool silent) { + if (silent) + return; + scoreLoad?.Cancel(); var menu = intro.ChildScreen; if (menu == null) { - scoreLoad = Schedule(() => LoadScore(score)); + scoreLoad = Schedule(() => LoadScore(score, false)); return; } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 5b98d92654..44556a6360 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -174,7 +174,7 @@ namespace osu.Game.Overlays.Direct }; } - private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() => + private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => { if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) progressBar.FadeOut(500); diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index a2a835a259..b619abbc2f 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap) { - beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false)); + beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false, false)); beatmaps.ItemAdded += addBeatmapSet; beatmaps.ItemRemoved += removeBeatmapSet; @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj, bool existing) => Schedule(() => + private void addBeatmapSet(BeatmapSetInfo obj, bool existing, bool silent) => Schedule(() => { if (existing) return; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 31fceebc93..2dc997d5ed 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -214,7 +214,7 @@ namespace osu.Game.Overlays beatmapSets.Insert(index, beatmapSetInfo); } - private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing) + private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing, bool silent) { if (existing) return; diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index e03bf856c9..23f35d5d3a 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.Settings.Sections private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray()); - private void itemAdded(SkinInfo s, bool existing) + private void itemAdded(SkinInfo s, bool existing, bool silent) { if (existing) return; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c44fba0c69..136f015080 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Play var score = CreateScoreInfo(); if (RulesetContainer.Replay == null) - scoreManager.Import(score); + scoreManager.Import(score, true); Push(new Results(score)); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b8458c4c70..f4af4f9068 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -505,7 +505,7 @@ namespace osu.Game.Screens.Select } } - private void onBeatmapSetAdded(BeatmapSetInfo s, bool existing) => Carousel.UpdateBeatmapSet(s); + private void onBeatmapSetAdded(BeatmapSetInfo s, bool existing, bool silent) => Carousel.UpdateBeatmapSet(s); private void onBeatmapSetRemoved(BeatmapSetInfo s) => Carousel.RemoveBeatmapSet(s); private void onBeatmapRestored(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); private void onBeatmapHidden(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); From a6b0e35b2d5252416bd0fac48fd9d4f1521634bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 18:31:54 +0900 Subject: [PATCH 69/76] Fix post-rebase issues --- osu.Game/OsuGame.cs | 27 ++++++++++++++------------- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 03ddc8da86..cd40d4793a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -263,18 +263,26 @@ namespace osu.Game return; } - var score = ScoreManager.GetScore(scoreInfo); - if (score.Replay == null) + var databasedScore = ScoreManager.GetScore(score); + var databasedScoreInfo = databasedScore.ScoreInfo; + if (databasedScore.Replay == null) { Logger.Log("The loaded score has no replay data.", LoggingTarget.Information); return; } + var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == databasedScoreInfo.Beatmap.ID); + if (databasedBeatmap == null) + { + Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); + return; + } + if (!currentScreen.AllowExternalScreenChange) { notifications.Post(new SimpleNotification { - Text = $"Click here to watch {scoreInfo.User.Username} on {scoreInfo.BeatmapInfo}", + Text = $"Click here to watch {databasedScoreInfo.User.Username} on {databasedScoreInfo.Beatmap}", Activated = () => { loadScore(); @@ -296,19 +304,12 @@ namespace osu.Game return; } - var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == scoreInfo.BeatmapInfo.ID); - if (databasedBeatmap == null) - { - Logger.Log("Tried to load a score for a beatmap we don't have!", LoggingTarget.Information); - return; - } - - ruleset.Value = score.Ruleset; + ruleset.Value = databasedScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Beatmap.Value.Mods.Value = score.Mods; + Beatmap.Value.Mods.Value = databasedScoreInfo.Mods; - currentScreen.Push(new PlayerLoader(new ReplayPlayer(score))); + currentScreen.Push(new PlayerLoader(new ReplayPlayer(databasedScore))); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 136f015080..01721775a0 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -291,7 +291,7 @@ namespace osu.Game.Screens.Play { var score = new ScoreInfo { - BeatmapInfo = Beatmap.Value.BeatmapInfo, + Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset, User = api.LocalUser.Value }; From 795933d1a1c52e6749f39a87374abd0dadd7f3ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 18:32:08 +0900 Subject: [PATCH 70/76] CreateScoreInfo -> CreateScore --- osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 01721775a0..bf44e9e636 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -276,7 +276,7 @@ namespace osu.Game.Screens.Play { if (!IsCurrentScreen) return; - var score = CreateScoreInfo(); + var score = CreateScore(); if (RulesetContainer.Replay == null) scoreManager.Import(score, true); @@ -287,7 +287,7 @@ namespace osu.Game.Screens.Play } } - protected virtual ScoreInfo CreateScoreInfo() + protected virtual ScoreInfo CreateScore() { var score = new ScoreInfo { diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 508933052a..fe77fd57f2 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -20,6 +20,6 @@ namespace osu.Game.Screens.Play RulesetContainer.SetReplay(score.Replay); } - protected override ScoreInfo CreateScoreInfo() => score.ScoreInfo; + protected override ScoreInfo CreateScore() => score.ScoreInfo; } } From 4144f4bd2f2ab8447cef37dfa71f24a3965bbd24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 18:40:06 +0900 Subject: [PATCH 71/76] Fix duplicates not being ignored if hash is null --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index b870b7dfc2..50767608af 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -508,7 +508,7 @@ namespace osu.Game.Database /// /// The new model proposed for import. Note that has not yet been run on this model. /// An existing model which matches the criteria to skip importing, else null. - protected virtual TModel CheckForExisting(TModel model) => ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); + protected virtual TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); private DbSet queryModel() => ContextFactory.Get().Set(); From 10ed09521cd6795f2724d179a14f07f170256efc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 18:30:43 +0900 Subject: [PATCH 72/76] Add leaderboard display for local scores --- osu.Game/Scoring/ScoreManager.cs | 2 ++ osu.Game/Screens/Select/Leaderboards/Leaderboard.cs | 9 +++++++-- osu.Game/Screens/Select/PlaySongSelect.cs | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index a2f156f6c3..663f441f2f 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -57,6 +57,8 @@ namespace osu.Game.Scoring public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + public IEnumerable QueryScores(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().Where(query); + public ScoreInfo Query(Expression> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query); } } diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 2b94c11bf9..714010b42c 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -179,6 +179,9 @@ namespace osu.Game.Screens.Select.Leaderboards private APIAccess api; private BeatmapInfo beatmap; + [Resolved] + private ScoreManager scoreManager { get; set; } + private ScheduledDelegate pendingUpdateScores; public BeatmapInfo Beatmap @@ -216,6 +219,8 @@ namespace osu.Game.Screens.Select.Leaderboards api.OnStateChange -= handleApiStateChange; } + public void RefreshScores() => updateScores(); + private GetScoresRequest getScoresRequest; private void handleApiStateChange(APIState oldState, APIState newState) @@ -242,8 +247,8 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == LeaderboardScope.Local) { - // TODO: get local scores from wherever here. - PlaceholderState = PlaceholderState.NoScores; + Scores = scoreManager.QueryScores(s => s.BeatmapInfo.ID == Beatmap.ID).ToArray(); + PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return; } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 1a405190e7..b5d333aee4 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -108,6 +108,8 @@ namespace osu.Game.Screens.Select removeAutoModOnResume = false; } + BeatmapDetails.Leaderboard.RefreshScores(); + Beatmap.Value.Track.Looping = true; base.OnResuming(last); From b1c5b43767073e76ab0514e381a6217dc974e8f1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 18:46:47 +0900 Subject: [PATCH 73/76] Fix post-rebase errors --- osu.Game/Screens/Select/Leaderboards/Leaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 714010b42c..a65cc6f096 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -247,7 +247,7 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == LeaderboardScope.Local) { - Scores = scoreManager.QueryScores(s => s.BeatmapInfo.ID == Beatmap.ID).ToArray(); + Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return; } From f80a30cba453f8fd53c2fec13326e3e14f846334 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 18:52:31 +0900 Subject: [PATCH 74/76] Fix null being serialized --- osu.Game/Scoring/ScoreInfo.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 07f1181a69..1ca62471f4 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -44,7 +44,8 @@ namespace osu.Game.Scoring { get { - if (mods != null) return mods; + if (mods != null) + return mods; if (modsJson == null) return Array.Empty(); @@ -65,7 +66,16 @@ namespace osu.Game.Scoring [Column("Mods")] public string ModsJson { - get => modsJson ?? (modsJson = JsonConvert.SerializeObject(mods)); + get + { + if (modsJson != null) + return modsJson; + + if (mods == null) + return null; + + return modsJson = JsonConvert.SerializeObject(mods); + } set { modsJson = value; From 17b2a4ca0de3c486ab239da7e278fcbb9a7d8cd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 19:46:40 +0900 Subject: [PATCH 75/76] Fix D rank displaying as F --- osu.Game/Scoring/ScoreRank.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index efc513c39c..2621c7d1e2 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -9,7 +9,7 @@ namespace osu.Game.Scoring { [Description(@"F")] F, - [Description(@"F")] + [Description(@"D")] D, [Description(@"C")] C, From 2860f5a5cdbee1deb8602ee07b11bdd95d6dcc98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 20:03:21 +0900 Subject: [PATCH 76/76] Revert "Fix D rank displaying as F" This reverts commit 17b2a4ca0de3c486ab239da7e278fcbb9a7d8cd9. --- osu.Game/Scoring/ScoreRank.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index 2621c7d1e2..efc513c39c 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -9,7 +9,7 @@ namespace osu.Game.Scoring { [Description(@"F")] F, - [Description(@"D")] + [Description(@"F")] D, [Description(@"C")] C,